var webview, dom = {},
    rotInfo = {
        idleTime: 3e3,
        speed: .15,
        pivot: [],
        stopWhenZoom: !1
    };

function getQueryVariable(e) {
    for (var t = window.location.search.substring(1).split("&"), i = 0; i < t.length; i++) {
        var s = t[i].split("=");
        if (s[0] == e)
            return s[1]
    }
    return !1
}
dom.addClass = function (e, t) {
        if (void 0 === e.className)
            e.className = t;
        else if (e.className !== t) {
            var i = e.className.split(/ +/); -
            1 == i.indexOf(t) && (i.push(t),
                e.className = i.join(" ").replace(/^\s+/, "").replace(/\s+$/, ""))
        }
    },
    dom.removeClass = function (e, t) {
        if (t)
            if (void 0 === e.className)
            ;
            else if (e.className === t)
            e.removeAttribute("class");
        else {
            var i = e.className.split(/ +/),
                s = i.indexOf(t); -
            1 != s && (i.splice(s, 1),
                e.className = i.join(" "))
        } else
            e.className = void 0
    },
    dom.hasClass = function (e, t) {
        return new RegExp("(?:^|\\s+)" + t + "(?:\\s+|$)").test(e.className) || !1
    },
    dom.id = function (e, t) {
        return (t = t || document).getElementById && t.getElementById(e) || document.getElementById(e)
    },
    dom.Tag = function (e, t) {
        return (t = t || document).getElementsByTagName(e)
    },
    dom.cla = function (e, t) {
        return (t = t || document).getElementsByClassName(e)
    },
    dom.ifVoid = function (e, t) {
        return null == e ? t : e
    },
    dom.objToArray = function (e) {
        if (e instanceof Array)
            return e;
        var t = [];
        for (var i in e)
            t.push(e[i]);
        return t
    };
var Clamp = function (e, t, i) {
        return void 0 === t && (t = 0),
            void 0 === i && (i = 1),
            Math.min(i, Math.max(t, e))
    },
    codeToCh = function (e) {
        return unescape(e)
    };
fdage = {
    // 背景颜色透明
    transparentBackground: true
},
    function (I) {

        function r(e, t, i) {
            if (this.name = t.partName,
                this.animatedProperties = [],
                this.sceneObjectType = t.sceneObjectType,
                this.skinningRigIndex = t.skinningRigIndex,
                this.id = i,
                this.mesh = this.skinningRig = 0,
                this.materialIndex = this.lightIndex = this.meshIndex = -1,
                this.emissiveProperty = this.offsetVProperty = this.offsetUProperty = this.material = 0,
                this.debugMe = t.debugMe,
                this.debugString = "",
                this.hasTransform = !1,
                this.modelPartIndex = t.modelPartIndex,
                this.modelPartFPS = t.modelPartFPS,
                this.modelPartScale = t.modelPartScale,
                this.parentIndex = t.parentIndex,
                this.totalFrames = t.totalFrames,
                this.animationLength = 1 / this.modelPartFPS * this.totalFrames,
                this.turnTableSpinOffset = this.turnTableSpin = this.spinProperty = this.dispersionProperty = this.lightIllumProperty = this.skyIllumProperty = this.opacityProperty = this.spotSharpnessProperty = this.spotAngleProperty = this.distanceProperty = this.brightnessProperty = this.blueProperty = this.greenProperty = this.redProperty = this.visibleProperty = 0,
                t.animatedProperties) {
                i = t.animatedProperties.length;
                for (var s = 0; s < i; ++s) {
                    var n = t.animatedProperties[s],
                        r = new a();
                    r.name = n.name,
                        this.animatedProperties.push(r),
                        "Red" != r.name || this.redProperty || (this.redProperty = r),
                        "Green" != r.name || this.greenProperty || (this.greenProperty = r),
                        "Blue" != r.name || this.blueProperty || (this.blueProperty = r),
                        "Brightness" != r.name || this.brightnessProperty || (this.brightnessProperty = r),
                        "Distance" != r.name || this.distanceProperty || (this.distanceProperty = r),
                        "Spot Angle" != r.name || this.spotAngleProperty || (this.spotAngleProperty = r),
                        "Spot Sharpness" != r.name || this.spotSharpnessProperty || (this.spotSharpnessProperty = r),
                        "Opacity" != r.name || this.opacityProperty || (this.opacityProperty = r),
                        "Sky Illumination" != r.name || this.skyIllumProperty || (this.skyIllumProperty = r),
                        "Light Illumination" != r.name || this.lightIllumProperty || (this.lightIllumProperty = r),
                        "Dispersion" != r.name || this.dispersionProperty || (this.dispersionProperty = r),
                        "Visible" != r.name || this.visibleProperty || (this.visibleProperty = r),
                        "Spin Rate" == r.name && (this.spinProperty = r),
                        "OffsetU" == r.name && (this.offsetUProperty = r),
                        "OffsetV" == r.name && (this.offsetVProperty = r),
                        "EmissiveIntensity" == r.name && (this.emissiveProperty = r)
                }
            }
            this.keyframesSharedBufferUShorts = this.keyframesSharedBufferFloats = this.keyFramesByteStream = 0,
                (e = e.get(t.file)) && (this.keyFramesByteStream = new u(e.data),
                    this.unPackKeyFrames()),
                this.animatedLocalTransform = new o(this),
                this.hasTransform = this.animatedLocalTransform.hasTranslation || this.animatedLocalTransform.hasRotation || this.animatedLocalTransform.hasScale,
                this.cachedWorldTransform0 = S.identity(),
                this.cachedWorldTransform1 = S.identity(),
                this.cachedWorldTransform2 = S.identity(),
                this.cachedWorldTransform3 = S.identity(),
                this.cachedFrame3 = this.cachedFrame2 = this.cachedFrame1 = this.cachedFrame0 = -10,
                this.cachedFrameUse3 = this.cachedFrameUse2 = this.cachedFrameUse1 = this.cachedFrameUse0 = 0,
                this.useFixedLocalTransform = this.useFixedWorldTransform = !1
        }

        function a() {
            this.currentValue = 0,
                this.keyframeBufferStartIndexFloat = -1,
                this.lastValue = this.interpolationOffsetUShort = this.frameIndexOffsetUShort = this.weighOutOffsetFloat = this.weighInOffsetFloat = this.valueOffsetFloat = this.indexUShortSkip = this.indexFloatSkip = this.interpolationType = this.bytesPerKeyFrame = this.keyframePackingType = 0,
                this.lastFramePercent = -10,
                this.enable = !0,
                this.name = "NONE",
                this.splineKF0 = new i(0, 0),
                this.splineKF1 = new i(0, 0),
                this.splineKF2 = new i(0, 0),
                this.splineKF3 = new i(0, 0),
                this.debugMe = !0,
                this.debugString = "",
                this.lastSearchIndex = 1,
                this.savedSearchIndex = 0,
                this.splineKF0.frameIndex = 0,
                this.splineKF1.frameIndex = 1,
                this.splineKF2.frameIndex = 2,
                this.splineKF3.frameIndex = 3,
                this.numKeyframes = 0
        }

        function o(e) {
            var t = e.animatedProperties;
            for (this.TX = this.TY = this.TZ = this.RX = this.RY = this.RZ = this.SX = this.SY = this.SZ = 0,
                this.hostObject = e,
                this.matrix = S.identity(),
                this.cachedmatrix0 = S.identity(),
                this.cachedmatrix1 = S.identity(),
                this.cachedmatrix2 = S.identity(),
                this.cachedmatrix3 = S.identity(),
                this.cachedFrame3 = this.cachedFrame2 = this.cachedFrame1 = this.cachedFrame0 = -1,
                this.cachedFrameUse3 = this.cachedFrameUse2 = this.cachedFrameUse1 = this.cachedFrameUse0 = 0,
                this.debugString = "",
                e = 0; e < t.length; e++) {
                var i = t[e];
                "Translation X" == i.name ? this.TX = i : "Translation Y" == i.name ? this.TY = i : "Translation Z" == i.name ? this.TZ = i : "Rotation X" == i.name ? this.RX = i : "Rotation Y" == i.name ? this.RY = i : "Rotation Z" == i.name ? this.RZ = i : "Scale X" == i.name ? this.SX = i : "Scale Y" == i.name ? this.SY = i : "Scale Z" == i.name && (this.SZ = i)
            }
            this.hasTranslation = this.TX && this.TY && this.TZ,
                this.hasRotation = this.RX && this.RY && this.RZ,
                this.hasScale = this.SX && this.SY && this.SZ,
                this.lockTransform = !1
        }

        function c(e, t) {
            if (this.originalFPS = 1,
                this.name = t.name,
                this.totalSeconds = t.length,
                this.originalFPS = t.originalFPS,
                this.totalFrames = t.totalFrames,
                this.expectedNumAnimatedObjects = t.numAnimatedObjects,
                this.animatedObjects = [],
                this.sceneTransform = S.identity(),
                this.debugString = "",
                t.animatedObjects)
                for (var i = t.animatedObjects.length, s = 0; s < i; ++s) {
                    var n = new r(e, t.animatedObjects[s], s);
                    this.animatedObjects.push(n),
                        this.debugString += n.debugString
                }
            this.meshObjects = [],
                this.lightObjects = [],
                this.materialObjects = [],
                this.turnTableObjects = [],
                this.cameraObjects = []
        }

        function h(e) {
            for (this.files = [],
                e = new u(e); !e.empty();) {
                var t = {};
                t.name = e.readCString(),
                    t.type = e.readCString();
                var i = e.readUint32(),
                    s = e.readUint32(),
                    n = e.readUint32();
                if (t.data = e.readBytes(s),
                    !(t.data.length < s)) {
                    if (1 & i && (t.data = this.decompress(t.data, n),
                            null === t.data))
                        continue;
                    this.files[t.name] = t
                }
            }
        }

        function l(e) {
            this.digits = new Uint16Array(e || 0)
        }

        function d(e) {
            for (var t = 0; t < e.length; ++t) {
                var i = e[t].bounds;
                if (void 0 === this.min)
                    this.min = [i.min[0], i.min[1], i.min[2]],
                    this.max = [i.max[0], i.max[1], i.max[2]];
                else
                    for (var s = 0; s < 3; ++s)
                        this.min[s] = Math.min(i.min[s], this.min[s]),
                        this.max[s] = Math.max(i.max[s], this.max[s])
            }
            this.min = this.min ? this.min : [0, 0, 0],
                this.max = this.max ? this.max : [0, 0, 0],
                this.center = [.5 * (this.min[0] + this.max[0]), .5 * (this.min[1] + this.max[1]), .5 * (this.min[2] + this.max[2])],
                this.radius = [this.max[0] - this.center[0], this.max[1] - this.center[1], this.max[2] - this.center[2]],
                this.radiusDiagonal = Math.sqrt(this.radius[0] * this.radius[0] + this.radius[1] * this.radius[1] + this.radius[2] * this.radius[2])
        }

        function p(e) {
            this.name = "none",
                this.text = "default text",
                this.title = "none",
                this.debugString = this.imagePath = "",
                this.controlRect = new s(e),
                this.defaultAlpha = .5,
                this.focusAlpha = 1,
                this.updateAlphas = !0,
                this.linkedBackground = this.backgroundOffsetY = this.backgroundOffsetX = this.edgePixelsY = this.edgePixelsX = this.backgroundBottomMiddle = this.backgroundBottomRight = this.backgroundBottomLeft = this.backgroundMiddleMiddle = this.backgroundMiddleRight = this.backgroundMiddleLeft = this.backgroundTopMiddle = this.backgroundTopRight = this.backgroundTopLeft = this.backgroundMiddle = this.backgroundRight = this.backgroundLeft = 0
        }

        function u(e) {
            this.bytes = new Uint8Array(e)
        }

        function s(e) {
            this.name = "none",
                this.title = "frame",
                this.yPercent = this.xPercent = 0,
                this.heightPercent = this.widthPercent = 1,
                this.debugString = "",
                this.parentControlRect = 0,
                this.childControlRects = [],
                this.clicked = this.mouseDown = this.mouseOver = !1,
                this.localMouseYPercent = this.localMouseXPercent = 0,
                this.enabled = this.visible = !0,
                this.opacity = 1,
                this.guiScreen = e,
                this.id = this.callBack = this.linkedControl = 0
        }
        r.prototype.setFixedWorldTransform = function (e) {
                this.useFixedWorldTransform = !0,
                    S.copy(this.cachedWorldTransform0, e)
            },
            r.prototype.setFixedLocalTransform = function (e) {
                this.useFixedLocalTransform = !0,
                    this.animatedLocalTransform.lockTransform = !0,
                    S.copy(this.animatedLocalTransform.cachedmatrix0, e)
            },
            r.prototype.getCachedWorldTransform = function (e) {
                return this.useFixedWorldTransform ? 0 : e == this.cachedFrame0 ? this.cachedmatrix0 : e == this.cachedFrame1 ? this.cachedmatrix1 : e == this.cachedFrame2 ? this.cachedmatrix2 : e == this.cachedFrame3 ? this.cachedmatrix3 : 0
            },
            r.prototype.getFreeCachedWorldTransform = function (e) {
                return this.useFixedWorldTransform ? 0 : (this.cachedFrameUse0--,
                    this.cachedFrameUse1--,
                    this.cachedFrameUse2--,
                    this.cachedFrameUse3--,
                    this.cachedFrameUse0 <= this.cachedFrameUse1 && this.cachedFrameUse0 <= this.cachedFrameUse2 && this.cachedFrameUse0 <= this.cachedFrameUse3 ? (this.cachedFrame0 = e,
                        this.cachedFrameUse0 = 0,
                        this.cachedWorldTransform0) : this.cachedFrameUse1 <= this.cachedFrameUse0 && this.cachedFrameUse1 <= this.cachedFrameUse2 && this.cachedFrameUse1 <= this.cachedFrameUse3 ? (this.cachedFrame1 = e,
                        this.cachedFrameUse1 = 0,
                        this.cachedWorldTransform1) : this.cachedFrameUse2 <= this.cachedFrameUse0 && this.cachedFrameUse2 <= this.cachedFrameUse1 && this.cachedFrameUse2 <= this.cachedFrameUse3 ? (this.cachedFrame2 = e,
                        this.cachedFrameUse2 = 0,
                        this.cachedWorldTransform2) : (this.cachedFrame3 = e,
                        this.cachedFrameUse3 = 0,
                        this.cachedWorldTransform3))
            },
            r.prototype.unPackKeyFrames = function () {
                if (this.keyFramesByteStream) {
                    var e = new Float32Array(this.keyFramesByteStream.bytes.buffer),
                        t = new Uint32Array(this.keyFramesByteStream.bytes.buffer),
                        i = new Uint16Array(this.keyFramesByteStream.bytes.buffer),
                        s = new Uint8Array(this.keyFramesByteStream.bytes.buffer);
                    this.keyframesSharedBufferFloats = e;
                    e = 0,
                        e = 1 + (t = (this.keyframesSharedBufferUShorts = t)[0]),
                        t = this.animatedProperties.length;
                    for (var n = 0; n < t; n++) {
                        var r = this.animatedProperties[n],
                            a = 2 + 2 * n,
                            o = 2 * a;
                        r.keyframeBufferStartIndexFloat = e,
                            r.numKeyframes = i[a],
                            r.keyframePackingType = s[2 + o],
                            r.interpolationType = s[3 + o],
                            r.indexFloatSkip = 0,
                            (r.indexUShortSkip = 0) < r.numKeyframes && (0 == r.keyframePackingType ? (r.bytesPerKeyFrame = 16,
                                r.indexFloatSkip = 4,
                                r.indexUShortSkip = 8,
                                r.valueOffsetFloat = 0,
                                r.weighInOffsetFloat = 1,
                                r.weighOutOffsetFloat = 2,
                                r.frameIndexOffsetUShort = 6,
                                r.interpolationOffsetUShort = 7) : 1 == r.keyframePackingType ? (r.bytesPerKeyFrame = 8,
                                r.indexFloatSkip = 2,
                                r.indexUShortSkip = 4,
                                r.valueOffsetFloat = 0,
                                r.weighInOffsetFloat = 0,
                                r.weighOutOffsetFloat = 0,
                                r.frameIndexOffsetUShort = 2,
                                r.interpolationOffsetUShort = 3) : 2 == r.keyframePackingType && (r.bytesPerKeyFrame = 4,
                                r.indexFloatSkip = 1,
                                r.indexUShortSkip = 2,
                                r.valueOffsetFloat = 0,
                                r.weighInOffsetFloat = 0,
                                r.weighOutOffsetFloat = 0,
                                r.frameIndexOffsetUShort = 0,
                                r.interpolationOffsetUShort = 0)),
                            e += r.numKeyframes * r.indexFloatSkip
                    }
                }
            },
            r.prototype.setupSkinningRig = function (e, t, i, s) {
                var n = S.identity(),
                    r = S.identity(),
                    a = (a = i * (o = e.animatedObjects[t]).modelPartFPS) - Math.floor(a),
                    o = (i = Math.floor(e.getObjectAnimationFramePercent(o, i))) + 1,
                    h = 1 - a,
                    l = s.skinningClusters.length;
                if (0 < l)
                    for (var d = 0; d < l; d++) {
                        (c = s.skinningClusters[d]).solveClusterTransformAtFrame(e, t, i, n),
                            c.solveClusterTransformAtFrame(e, t, o, r);
                        for (var c = c.matrix, u = 0; u < 16; u++)
                            c[u] = n[u] * h + r[u] * a
                    }
            },
            r.prototype.evaluateLocalTransformAtFramePercent = function (e, t, i, s) {
                if (this.useFixedLocalTransform)
                    S.copy(t, this.animatedLocalTransform.cachedmatrix0);
                else {
                    var n = 0;
                    s && (n = this.animatedLocalTransform.getCachedTransform(e)),
                        n ? S.copy(t, n) : ((n = this.animatedLocalTransform.getFreeCachedTransform(e)) ? (this.animatedLocalTransform.evaluateMatrix(n, this.totalFrames, e, i),
                                S.copy(t, n)) : this.animatedLocalTransform.evaluateMatrix(t, this.totalFrames, e, i),
                            0 != this.turnTableSpin && (e = S.rotation(S.empty(), this.turnTableSpin, 1),
                                S.mul(t, t, e)))
                }
            },
            r.prototype.hasAnimatedTransform = function () {
                var e = this.animatedLocalTransform;
                return !!(e.TX && 1 < e.TX.numKeyframes || e.TY && 1 < e.TY.numKeyframes || e.TZ && 1 < e.TZ.numKeyframes || e.RX && 1 < e.RX.numKeyframes || e.RY && 1 < e.RY.numKeyframes || e.RZ && 1 < e.RZ.numKeyframes || e.SX && 1 < e.SX.numKeyframes || e.SY && 1 < e.SY.numKeyframes || e.SZ && 1 < e.SZ.numKeyframes)
            },
            a.prototype.evaluateCurve = function (e, t) {
                var i = this.splineKF1.frameIndex,
                    s = this.splineKF2.frameIndex,
                    n = this.splineKF1.value,
                    r = this.splineKF2.value,
                    a = i - (this.splineKF2.frameIndex - this.splineKF0.frameIndex),
                    o = s - (this.splineKF1.frameIndex - this.splineKF3.frameIndex),
                    h = n - (this.splineKF2.value - this.splineKF0.value) * this.splineKF1.weighOut,
                    l = r - (this.splineKF1.value - this.splineKF3.value) * this.splineKF2.weighIn;
                return 3 == this.splineKF1.interpolation && (a = i - (this.splineKF2.frameIndex - this.splineKF1.frameIndex),
                        h = n - this.splineKF1.weighOut),
                    3 == this.splineKF2.interpolation && (o = s - (this.splineKF1.frameIndex - this.splineKF2.frameIndex),
                        l = r + this.splineKF2.weighIn),
                    a = (e - a) / (i - a),
                    i = (e - i) / (s - i),
                    s = (e - s) / (o - s),
                    ((h * (1 - a) + n * a) * (1 - i) + (o = n * (1 - i) + r * i) * i) * (1 - i) + ((r * (1 - s) + l * s) * i + o * (1 - i)) * i
            },
            a.prototype.evaluate = function (e, t, i) {
                if (!i)
                    return t;
                if (0 == this.numKeyframes)
                    return this.lastValue = t;
                if (1 == this.numKeyframes)
                    return this.lastValue = 2 == this.keyframePackingType ? i.keyframesSharedBufferFloats[this.keyframeBufferStartIndexFloat] : i.keyframesSharedBufferFloats[this.keyframeBufferStartIndexFloat + this.valueOffsetFloat];
                if (this.lastFramePercent == e)
                    return this.lastValue;
                var s = this.keyframeBufferStartIndexFloat,
                    n = 2 * this.keyframeBufferStartIndexFloat;
                if (this.lastValue = t,
                    this.lastFramePercent = e,
                    2 == this.keyframePackingType) {
                    var r = e - (t = Math.floor(e));
                    return e >= this.numKeyframes && (t -= Math.floor(e / this.numKeyframes) * this.numKeyframes),
                        t >= this.numKeyframes ? this.lastValue = i.keyframesSharedBufferFloats[s + (this.numKeyframes - 1)] : t < 0 ? this.lastValue = i.keyframesSharedBufferFloats[s] : 0 == r ? this.lastValue = i.keyframesSharedBufferFloats[s + t] : (e = n = i.keyframesSharedBufferFloats[s + t],
                            ++t >= this.numKeyframes && (t -= this.numKeyframes),
                            0 <= t && t < this.numKeyframes ? e = n * (1 - r) + i.keyframesSharedBufferFloats[s + t] * r : i.debugString += "<br>bad lerp frame " + t + " of " + this.numKeyframes,
                            this.lastValue = e)
                }
                var a = this.numKeyframes;
                r = i.keyframesSharedBufferUShorts[n + this.frameIndexOffsetUShort];
                if (e >= i.keyframesSharedBufferUShorts[n + (a - 1) * this.indexUShortSkip + this.frameIndexOffsetUShort])
                    return this.lastValue = i.keyframesSharedBufferFloats[s + (a - 1) * this.indexFloatSkip + this.valueOffsetFloat];
                if (e < r)
                    return this.lastValue = i.keyframesSharedBufferFloats[s + this.valueOffsetFloat];
                this.lastSearchIndex < this.numKeyframes && e > i.keyframesSharedBufferUShorts[n + this.lastSearchIndex * this.indexUShortSkip + this.frameIndexOffsetUShort] && (this.lastSearchIndex = 1);
                for (var o = this.lastSearchIndex; o < a; o++) {
                    r = s + o * this.indexFloatSkip;
                    var h = s + (o - 1) * this.indexFloatSkip,
                        l = n + o * this.indexUShortSkip,
                        d = n + (o - 1) * this.indexUShortSkip;
                    if (e >= i.keyframesSharedBufferUShorts[d + this.frameIndexOffsetUShort] && e <= i.keyframesSharedBufferUShorts[l + this.frameIndexOffsetUShort]) {
                        this.lastSearchIndex = o;
                        var c = i.keyframesSharedBufferUShorts[d + this.interpolationOffsetUShort];
                        if (2 == c) {
                            this.lastValue = e = e >= i.keyframesSharedBufferUShorts[l + this.frameIndexOffsetUShort] ? i.keyframesSharedBufferFloats[r + this.valueOffsetFloat] : i.keyframesSharedBufferFloats[h + this.valueOffsetFloat];
                            break
                        }
                        if (0 == c) {
                            s = i.keyframesSharedBufferUShorts[d + this.frameIndexOffsetUShort],
                                t = i.keyframesSharedBufferFloats[h + this.valueOffsetFloat],
                                n = i.keyframesSharedBufferFloats[r + this.valueOffsetFloat],
                                r = (e - s) / (i.keyframesSharedBufferUShorts[l + this.frameIndexOffsetUShort] - s),
                                this.lastValue = e = t * (1 - r) + n * r;
                            break
                        }
                        if (1 == c || 3 == c) {
                            var u = c = !1,
                                f = 0,
                                m = i.keyframesSharedBufferFloats[h + this.valueOffsetFloat],
                                p = i.keyframesSharedBufferFloats[r + this.valueOffsetFloat],
                                g = 0,
                                v = 0,
                                x = (d = i.keyframesSharedBufferUShorts[d + this.frameIndexOffsetUShort],
                                    l = i.keyframesSharedBufferUShorts[l + this.frameIndexOffsetUShort],
                                    0),
                                y = 1,
                                b = 1,
                                S = 1,
                                T = 1,
                                w = 1,
                                C = 1,
                                R = 1,
                                A = 1;
                            0 != this.weighInOffsetFloat && (b = i.keyframesSharedBufferFloats[h + this.weighInOffsetFloat],
                                    S = i.keyframesSharedBufferFloats[r + this.weighInOffsetFloat],
                                    C = i.keyframesSharedBufferFloats[h + this.weighOutOffsetFloat],
                                    R = i.keyframesSharedBufferFloats[r + this.weighOutOffsetFloat]),
                                1 < o && (c = !0,
                                    f = i.keyframesSharedBufferFloats[s + (o - 2) * this.indexFloatSkip + this.valueOffsetFloat],
                                    v = i.keyframesSharedBufferUShorts[n + (o - 2) * this.indexUShortSkip + this.frameIndexOffsetUShort],
                                    0 != this.weighInOffsetFloat && (y = i.keyframesSharedBufferFloats[s + (o - 2) * this.indexFloatSkip + this.weighInOffsetFloat],
                                        w = i.keyframesSharedBufferFloats[s + (o - 2) * this.indexFloatSkip + this.weighOutOffsetFloat])),
                                o < a - 1 && (u = !0,
                                    g = i.keyframesSharedBufferFloats[s + (o + 1) * this.indexFloatSkip + this.valueOffsetFloat],
                                    x = i.keyframesSharedBufferUShorts[n + (o + 1) * this.indexUShortSkip + this.frameIndexOffsetUShort],
                                    0 != this.weighInOffsetFloat && (T = i.keyframesSharedBufferFloats[s + (o + 1) * this.indexFloatSkip + this.weighInOffsetFloat],
                                        A = i.keyframesSharedBufferFloats[s + (o + 1) * this.indexFloatSkip + this.weighOutOffsetFloat])),
                                c && u ? (this.splineKF0.value = f,
                                    this.splineKF1.value = m,
                                    this.splineKF2.value = p,
                                    this.splineKF3.value = g,
                                    this.splineKF0.frameIndex = v,
                                    this.splineKF1.frameIndex = d,
                                    this.splineKF2.frameIndex = l,
                                    this.splineKF3.frameIndex = x,
                                    this.splineKF0.weighIn = y,
                                    this.splineKF0.weighOut = w,
                                    this.splineKF1.weighIn = b,
                                    this.splineKF1.weighOut = C,
                                    this.splineKF2.weighIn = S,
                                    this.splineKF2.weighOut = R,
                                    this.splineKF3.weighIn = T,
                                    this.splineKF3.weighOut = A) : (this.splineKF0.value = m,
                                    this.splineKF1.value = m,
                                    this.splineKF2.value = p,
                                    this.splineKF3.value = p,
                                    this.splineKF0.frameIndex = d,
                                    this.splineKF1.frameIndex = d,
                                    this.splineKF2.frameIndex = l,
                                    this.splineKF3.frameIndex = l,
                                    this.splineKF1.weighIn = b,
                                    this.splineKF2.weighIn = S,
                                    this.splineKF1.weighOut = C,
                                    this.splineKF2.weighOut = R,
                                    u ? (this.splineKF3.value = g,
                                        this.splineKF3.frameIndex = x,
                                        this.splineKF3.weighIn = T,
                                        this.splineKF3.weighOut = A) : (this.splineKF3.frameIndex++,
                                        this.splineKF3.value = this.splineKF1.value,
                                        this.splineKF3.weighIn = 1,
                                        this.splineKF3.weighOut = 1),
                                    c ? (this.splineKF0.value = f,
                                        this.splineKF0.frameIndex = v,
                                        this.splineKF0.weighIn = y,
                                        this.splineKF0.weighOut = w) : (this.splineKF0.value = this.splineKF2.value,
                                        this.splineKF0.weighIn = 1,
                                        this.splineKF0.weighOut = 1,
                                        0 < this.splineKF0.frameIndex ? this.splineKF0.frameIndex-- : (this.splineKF1.frameIndex++,
                                            this.splineKF2.frameIndex++,
                                            this.splineKF3.frameIndex++,
                                            e++))),
                                this.lastValue = e = this.evaluateCurve(e, t);
                            break
                        }
                    }
                }
                return this.lastValue
            },
            o.prototype.getTRSValue = function (e, t, i) {
                return t ? (t.evaluate(e, i, this.hostObject),
                    "" != t.debugString && (this.debugString += t.debugString),
                    t.lastValue) : i
            },
            o.prototype.evaluateMatrix = function (e, t, i, s) {
                if (this.lockTransform)
                    S.copy(e, this.cachedmatrix0);
                else {
                    var n = 0,
                        r = t = 0;
                    n = r = t = 0,
                        n = r = t = 1;
                    this.hasRotation ? (n = this.getTRSValue(i, this.RX, 0),
                            t = this.getTRSValue(i, this.RY, 0),
                            r = this.getTRSValue(i, this.RZ, 0),
                            s ? (this.matrix = S.rotation(S.empty(), r, 2),
                                s = S.rotation(S.empty(), n, 0),
                                S.mul(s, s, this.matrix),
                                this.matrix = S.rotation(S.empty(), t, 1)) : (this.matrix = S.rotation(S.empty(), n, 0),
                                s = S.rotation(S.empty(), t, 1),
                                S.mul(s, s, this.matrix),
                                this.matrix = S.rotation(S.empty(), r, 2)),
                            S.mul(this.matrix, this.matrix, s)) : S.copy(this.matrix, S.identity()),
                        this.hasTranslation && (t = this.getTRSValue(i, this.TX, 0),
                            r = this.getTRSValue(i, this.TY, 0),
                            n = this.getTRSValue(i, this.TZ, 0),
                            this.matrix[12] = t,
                            this.matrix[13] = r,
                            this.matrix[14] = n),
                        this.hasScale && (t = this.getTRSValue(i, this.SX, 1),
                            r = this.getTRSValue(i, this.SY, 1),
                            n = this.getTRSValue(i, this.SZ, 1),
                            this.matrix[0] *= t,
                            this.matrix[4] *= r,
                            this.matrix[8] *= n,
                            this.matrix[1] *= t,
                            this.matrix[5] *= r,
                            this.matrix[9] *= n,
                            this.matrix[2] *= t,
                            this.matrix[6] *= r,
                            this.matrix[10] *= n,
                            this.matrix[3] *= t,
                            this.matrix[7] *= r,
                            this.matrix[11] *= n),
                        S.copy(e, this.matrix)
                }
            },
            o.prototype.clearCachedTransforms = function () {
                this.cachedFrame3 = this.cachedFrame2 = this.cachedFrame1 = this.cachedFrame0 = -1,
                    this.cachedFrameUse3 = this.cachedFrameUse2 = this.cachedFrameUse1 = this.cachedFrameUse0 = 0,
                    this.TX && (this.TX.lastFramePercent = -10),
                    this.TY && (this.TY.lastFramePercent = -10),
                    this.TZ && (this.TZ.lastFramePercent = -10),
                    this.RX && (this.RX.lastFramePercent = -10),
                    this.RY && (this.RY.lastFramePercent = -10),
                    this.RZ && (this.RZ.lastFramePercent = -10),
                    this.SX && (this.SX.lastFramePercent = -10),
                    this.SY && (this.SY.lastFramePercent = -10),
                    this.SZ && (this.SZ.lastFramePercent = -10),
                    this.lockTransform = !1
            },
            o.prototype.getCachedTransform = function (e) {
                return this.lockTransform ? 0 : this.cachedFrame0 == e ? this.cachedmatrix0 : this.cachedFrame1 == e ? this.cachedmatrix1 : this.cachedFrame2 == e ? this.cachedmatrix2 : this.cachedFrame3 == e ? this.cachedmatrix3 : 0
            },
            o.prototype.getFreeCachedTransform = function (e) {
                return this.lockTransform ? 0 : (this.cachedFrameUse0--,
                    this.cachedFrameUse1--,
                    this.cachedFrameUse2--,
                    this.cachedFrameUse3--,
                    this.cachedFrameUse0 <= this.cachedFrameUse1 && this.cachedFrameUse0 <= this.cachedFrameUse2 && this.cachedFrameUse0 <= this.cachedFrameUse3 || this.cachedFrame0 == e ? (this.cachedFrame0 = e,
                        this.cachedFrameUse0 = 0,
                        this.cachedmatrix0) : this.cachedFrameUse1 <= this.cachedFrameUse0 && this.cachedFrameUse1 <= this.cachedFrameUse2 && this.cachedFrameUse1 <= this.cachedFrameUse3 || this.cachedFrame1 == e ? (this.cachedFrame1 = e,
                        this.cachedFrameUse1 = 0,
                        this.cachedmatrix1) : this.cachedFrameUse2 <= this.cachedFrameUse0 && this.cachedFrameUse2 <= this.cachedFrameUse1 && this.cachedFrameUse2 <= this.cachedFrameUse3 || this.cachedFrame2 == e ? (this.cachedFrame2 = e,
                        this.cachedFrameUse2 = 0,
                        this.cachedmatrix2) : (this.cachedFrame3 = e,
                        this.cachedFrameUse3 = 0,
                        this.cachedmatrix3))
            },
            c.prototype.evaluateModelPartTransformAtFrame = function (e, t, i, s) {
                S.copy(i, S.identity());
                for (var n = 0; n < 100; n++) {
                    var r = this.animatedObjects[e];
                    if (e == r.parentIndex)
                        break;
                    if (r.useFixedWorldTransform) {
                        S.mul(i, r.cachedWorldTransform0, i);
                        break
                    }
                    var a = 0;
                    if (s && (a = r.getCachedWorldTransform(t)),
                        a) {
                        S.mul(i, a, i);
                        break
                    }
                    a = S.identity(),
                        r.evaluateLocalTransformAtFramePercent(t, a, !1, s),
                        S.mul(i, a, i),
                        e == r.parentIndex && (n = 100),
                        e = r.parentIndex
                }
            },
            c.prototype.lerpModelPartTransform = function (e, t, i, s) {
                var n = this.animatedObjects[e];
                if (n.useFixedWorldTransform)
                    S.copy(i, n.cachedWorldTransform0);
                else {
                    var r = (r = t * n.modelPartFPS) - Math.floor(r),
                        a = Math.floor(this.getObjectAnimationFramePercent(n, t)),
                        o = a + 1,
                        h = t = 0;
                    for (s && (t = n.getCachedWorldTransform(a),
                            h = n.getCachedWorldTransform(o)),
                        t || ((t = n.getFreeCachedWorldTransform(a)) || (t = S.identity()),
                            this.evaluateModelPartTransformAtFrame(e, a, t, s)),
                        h || ((h = n.getFreeCachedWorldTransform(o)) || (h = S.identity()),
                            this.evaluateModelPartTransformAtFrame(e, o, h, s)),
                        e = 1 - r,
                        s = 0; s < 16; s++)
                        i[s] = t[s] * e + h[s] * r
                }
            },
            c.prototype.getModelPartTransform = function (e, t, i, s) {
                this.lerpModelPartTransform(e, t, i, s)
            },
            c.prototype.getAnimatedLocalTransform = function (e, t, i, s) {
                e = this.animatedObjects[e];
                var n = this.animatedObjects[e.parentIndex],
                    r = n.modelPartIndex != n.id,
                    a = S.identity();
                if (this.getModelPartTransform(e.modelPartIndex, t, a, s),
                    r) {
                    r = S.identity();
                    var o = S.identity();
                    this.getModelPartTransform(n.modelPartIndex, t, r, s),
                        S.invert(o, r),
                        S.mul(i, o, a),
                        i[12] *= e.modelPartScale,
                        i[13] *= e.modelPartScale,
                        i[14] *= e.modelPartScale
                } else
                    S.copy(i, a)
            },
            c.prototype.isVisibleAtFramePercent = function (e, t) {
                for (var i = e, s = 0, n = 0; n < 100; n++) {
                    if ((s = this.animatedObjects[i]).visibleProperty) {
                        if (s.visibleProperty.evaluate(t, 1, s),
                            "" != s.debugString || "" != s.visibleProperty.debugString)
                            return this.debugString += s.debugString,
                                this.debugString += s.visibleProperty.debugString,
                                !1;
                        if (0 == s.visibleProperty.lastValue)
                            return !1
                    }
                    i == s.parentIndex && (n = 100),
                        i = s.parentIndex
                }
                return !0
            },
            c.prototype.getWorldTransform = function (e, t, i, s, n) {
                if ((e = this.animatedObjects[e]).useFixedWorldTransform)
                    S.copy(i, e.cachedWorldTransform0);
                else {
                    var r = this.getObjectAnimationFramePercent(e, t),
                        a = S.identity();
                    if (e.evaluateLocalTransformAtFramePercent(r, a, !0, n),
                        r = e.modelPartIndex != e.id) {
                        r = S.identity();
                        var o = S.identity();
                        S.copy(o, a),
                            this.getAnimatedLocalTransform(e.id, t, r),
                            S.mul(a, r, o)
                    }
                    if (S.copy(i, a),
                        e.parentIndex != e.id)
                        for (var h = e.parentIndex, l = 0; l < 100; l++)
                            e = this.animatedObjects[h],
                            r = this.getObjectAnimationFramePercent(e, t),
                            a = S.identity(),
                            e.evaluateLocalTransformAtFramePercent(r, a, !0, n),
                            (r = e.modelPartIndex != e.id) ? (r = S.identity(),
                                this.getAnimatedLocalTransform(e.id, t, r),
                                o = S.identity(),
                                S.mul(o, a, i),
                                S.mul(i, r, o)) : (o = S.identity(),
                                S.copy(o, i),
                                S.mul(i, a, o)),
                            h == e.parentIndex && (l = 100),
                            h = e.parentIndex;
                    i[12] *= s,
                        i[13] *= s,
                        i[14] *= s
                }
            },
            c.prototype.hasParentInHierarchy = function (e, t) {
                for (var i = e.parentIndex, s = 0; s < 100; s++) {
                    if ((e = this.animatedObjects[i]).id == t)
                        return !0;
                    i == e.parentIndex && (s = 100),
                        i = e.parentIndex
                }
                return !1
            },
            c.prototype.hasParentTypeInHierarchy = function (e, t) {
                for (var i = e.parentIndex, s = 0; s < 100; s++) {
                    if ((e = this.animatedObjects[i]).sceneObjectType == t)
                        return !0;
                    i == e.parentIndex && (s = 100),
                        i = e.parentIndex
                }
                return !1
            },
            c.prototype.searchAnimationUpHierarchy = function (e) {
                for (var t = e.id, i = 0; i < 100; i++) {
                    if ((e = this.animatedObjects[t]).animatedLocalTransform && (e.hasAnimatedTransform() || e.id != e.modelPartIndex && this.searchAnimationUpHierarchy(this.animatedObjects[e.modelPartIndex])))
                        return !0;
                    t == e.parentIndex && (i = 100),
                        t = e.parentIndex
                }
                return !1
            },
            c.prototype.hasAnimationInHierarchy = function (e) {
                return !!(this.searchAnimationUpHierarchy(e) || e.id != e.modelPartIndex && this.searchAnimationUpHierarchy(this.animatedObjects[e.modelPartIndex]) || this.hasParentTypeInHierarchy(e, "TurnTableSO") || this.hasParentTypeInHierarchy(e, "CameraSO") || "CameraSO" == e.sceneObjectType)
            },
            c.prototype.getObjectAnimationFramePercent = function (e, t) {
                if (0 == this.totalFrames || 0 == e.animationLength)
                    return 0;
                var i = t / e.animationLength;
                i = Math.floor(i);
                return (i = (t -= e.animationLength * i) * e.modelPartFPS) >= e.totalFrames + 1 && (i = e.totalFrames),
                    i
            },
            h.prototype.get = function (e) {
                return this.files[e]
            },
            h.prototype.extract = function (e) {
                var t = this.files[e];
                return delete this.files[e],
                    t
            },
            h.prototype.checkSignature = function (e) {
                if (!e)
                    return !1;
                var t = this.get(e.name + ".sig");
                if (!t)
                    return !1;
                if (!(t = JSON.parse(String.fromCharCode.apply(null, t.data))))
                    return !1;
                for (var i = 5381, s = 0; s < e.data.length; ++s)
                    i = 33 * i + e.data[s] & 4294967295;
                return (e = new l()).setBytes([0, 233, 33, 170, 116, 86, 29, 195, 228, 46, 189, 3, 185, 31, 245, 19, 159, 105, 73, 190, 158, 80, 175, 38, 210, 116, 221, 229, 171, 134, 104, 144, 140, 5, 99, 255, 208, 78, 248, 215, 172, 44, 79, 83, 5, 244, 152, 19, 92, 137, 112, 10, 101, 142, 209, 100, 244, 92, 190, 125, 28, 0, 185, 54, 143, 247, 49, 37, 15, 254, 142, 180, 185, 232, 50, 219, 11, 186, 106, 116, 78, 212, 10, 105, 53, 26, 14, 181, 80, 47, 87, 213, 182, 19, 126, 151, 86, 109, 182, 224, 37, 135, 80, 59, 22, 93, 125, 68, 214, 106, 209, 152, 235, 157, 249, 245, 48, 76, 203, 0, 0, 95, 200, 246, 243, 229, 85, 79, 169], !0),
                    (s = new l()).setBytes(t[0]),
                    s.powmod(65537, e).toInt32() == i
            },
            h.prototype.decompress = function (e, t) {
                var i = new Uint8Array(t),
                    s = 0,
                    n = new Uint32Array(4096),
                    r = new Uint32Array(4096),
                    a = 256,
                    o = e.length,
                    h = 0,
                    l = 1,
                    d = 0,
                    c = 1;
                i[s++] = e[0];
                for (var u = 1; !(o <= (c = u + (u >> 1)) + 1); u++) {
                    d = e[c + 1],
                        c = e[c];
                    if ((f = 1 & u ? d << 4 | c >> 4 : (15 & d) << 8 | c) < a)
                        if (f < 256)
                            d = s,
                            c = 1,
                            i[s++] = f;
                        else {
                            d = s,
                                c = r[f];
                            for (var f, m = (f = n[f]) + c; f < m;)
                                i[s++] = i[f++]
                        }
                    else {
                        if (f != a)
                            break;
                        for (d = s,
                            c = l + 1,
                            m = (f = h) + l; f < m;)
                            i[s++] = i[f++];
                        i[s++] = i[h]
                    }
                    n[a] = h,
                        r[a++] = l + 1,
                        h = d,
                        l = c,
                        a = 4096 <= a ? 256 : a
                }
                return s == t ? i : null
            },
            l.prototype.setBytes = function (e, t) {
                var i = (e.length + 1) / 2 | 0;
                if (this.digits = new Uint16Array(i),
                    t) {
                    var s = 0;
                    for (i = e.length - 1; 0 <= i; i -= 2)
                        this.digits[s++] = e[i] + (0 < i ? 256 * e[i - 1] : 0)
                } else
                    for (s = 0; s < i; ++s)
                        this.digits[s] = e[2 * s] + 256 * e[2 * s + 1];
                this.trim()
            },
            l.prototype.toInt32 = function () {
                var e = 0;
                return 0 < this.digits.length && (e = this.digits[0],
                        1 < this.digits.length && (e |= this.digits[1] << 16)),
                    e
            },
            l.prototype.lessThan = function (e) {
                if (this.digits.length == e.digits.length)
                    for (var t = this.digits.length - 1; 0 <= t; --t) {
                        var i = this.digits[t],
                            s = e.digits[t];
                        if (i != s)
                            return i < s
                    }
                return this.digits.length < e.digits.length
            },
            l.prototype.shiftRight = function () {
                for (var e = 0, t = this.digits, i = t.length - 1; 0 <= i; --i) {
                    var s = t[i];
                    t[i] = s >> 1 | e << 15,
                        e = s
                }
                this.trim()
            },
            l.prototype.shiftLeft = function (e) {
                if (0 < e) {
                    for (var t = e / 16 | 0, i = 16 - (e %= 16), s = this.digits.length + t + 1, n = new l(s), r = 0; r < s; ++r)
                        n.digits[r] = 65535 & ((r < t || r >= this.digits.length + t ? 0 : this.digits[r - t]) << e | (r < 1 + t ? 0 : this.digits[r - t - 1]) >>> i);
                    return n.trim(),
                        n
                }
                return new l(this)
            },
            l.prototype.bitCount = function () {
                var e = 0;
                if (0 < this.digits.length) {
                    e = 16 * (this.digits.length - 1);
                    for (var t = this.digits[this.digits.length - 1]; t;)
                        t >>>= 1,
                        ++e
                }
                return e
            },
            l.prototype.sub = function (e) {
                var t = this.digits,
                    i = e.digits,
                    s = this.digits.length;
                e = e.digits.length;
                for (var n = 0, r = 0; r < s; ++r) {
                    var a, o = (o = t[r]) + ((n = o < (a = (a = r < e ? i[r] : 0) + n) ? 1 : 0) << 16);
                    t[r] = o - a & 65535
                }
                this.trim()
            },
            l.prototype.mul = function (e) {
                for (var t = new l(this.digits.length + e.digits.length), i = t.digits, s = 0; s < this.digits.length; ++s)
                    for (var n = this.digits[s], r = 0; r < e.digits.length; ++r)
                        for (var a = n * e.digits[r], o = s + r; a;) {
                            var h = (65535 & a) + i[o];
                            i[o] = 65535 & h,
                                a >>>= 16,
                                a += h >>> 16,
                                ++o
                        }
                return t.trim(),
                    t
            },
            l.prototype.mod = function (e) {
                if (this.digits.length <= 0 || e.digits.length <= 0)
                    return new l(0);
                var t = new l(this.digits);
                if (!this.lessThan(e)) {
                    for (var i = (i = new l(e.digits)).shiftLeft(t.bitCount() - i.bitCount()); !t.lessThan(e);)
                        i.lessThan(t) && t.sub(i),
                        i.shiftRight();
                    t.trim()
                }
                return t
            },
            l.prototype.powmod = function (e, t) {
                for (var i = new l([1]), s = this.mod(t); e;)
                    1 & e && (i = i.mul(s).mod(t)),
                    e >>>= 1,
                    s = s.mul(s).mod(t);
                return i
            },
            l.prototype.trim = function () {
                for (var e = this.digits.length; 0 < e && 0 == this.digits[e - 1];)
                    --e;
                e != this.digits.length && (this.digits = this.digits.subarray(0, e))
            },
            p.prototype.setBackground3x1 = function (e, t, i, s, n, r, a) {
                this.backgroundOffsetX = t,
                    this.backgroundOffsetY = i,
                    this.edgePixelsX = a,
                    this.backgroundLeft = e.addImage(s),
                    this.backgroundMiddle = e.addImage(n),
                    this.backgroundRight = e.addImage(r),
                    this.backgroundLeft.linkedControl.style.zIndex = "0",
                    this.backgroundMiddle.linkedControl.style.zIndex = "0",
                    this.backgroundRight.linkedControl.style.zIndex = "0",
                    this.setOpacity(this.defaultAlpha)
            },
            p.prototype.setBackground3x3 = function (e, t, i, s, n, r, a, o, h, l, d, c, u, f) {
                this.backgroundOffsetX = t,
                    this.backgroundOffsetY = i,
                    this.edgePixelsX = u,
                    this.edgePixelsY = f,
                    this.backgroundTopLeft = e.addImage(s),
                    this.backgroundMiddleLeft = e.addImage(a),
                    this.backgroundBottomLeft = e.addImage(l),
                    this.backgroundTopMiddle = e.addImage(n),
                    this.backgroundMiddleMiddle = e.addImage(o),
                    this.backgroundBottomMiddle = e.addImage(d),
                    this.backgroundTopRight = e.addImage(r),
                    this.backgroundMiddleRight = e.addImage(h),
                    this.backgroundBottomRight = e.addImage(c),
                    this.backgroundTopLeft.linkedControl.style.zIndex = "0",
                    this.backgroundTopRight.linkedControl.style.zIndex = "0",
                    this.backgroundTopMiddle.linkedControl.style.zIndex = "0",
                    this.backgroundMiddleLeft.linkedControl.style.zIndex = "0",
                    this.backgroundMiddleRight.linkedControl.style.zIndex = "0",
                    this.backgroundMiddleMiddle.linkedControl.style.zIndex = "0",
                    this.backgroundBottomLeft.linkedControl.style.zIndex = "0",
                    this.backgroundBottomRight.linkedControl.style.zIndex = "0",
                    this.backgroundBottomMiddle.linkedControl.style.zIndex = "0",
                    this.setOpacity(this.defaultAlpha)
            },
            p.prototype.alignBackground = function () {
                var e = (n = (s = this.controlRect).guiScreen).left * (1 - s.getScreenXPercent()),
                    t = n.bottom * (1 - s.getScreenYPercent()),
                    i = n.width * s.getScreenWidthPercent(),
                    s = n.height * s.getScreenHeightPercent();
                t += this.backgroundOffsetY,
                    e += this.backgroundOffsetX;
                if (this.backgroundTopLeft && this.backgroundTopRight && this.backgroundTopMiddle && this.backgroundMiddleLeft && this.backgroundMiddleRight && this.backgroundMiddleMiddle && this.backgroundBottomLeft && this.backgroundBottomRight && this.backgroundBottomMiddle) {
                    var n = i - 2 * this.edgePixelsX,
                        r = s - 2 * this.edgePixelsY;
                    this.backgroundTopLeft.linkedControl.style.height = this.edgePixelsY + "px",
                        this.backgroundTopMiddle.linkedControl.style.height = this.edgePixelsY + "px",
                        this.backgroundTopRight.linkedControl.style.height = this.edgePixelsY + "px",
                        this.backgroundBottomLeft.linkedControl.style.height = this.edgePixelsY + "px",
                        this.backgroundBottomMiddle.linkedControl.style.height = this.edgePixelsY + "px",
                        this.backgroundBottomRight.linkedControl.style.height = this.edgePixelsY + "px",
                        this.backgroundMiddleLeft.linkedControl.style.height = r + "px",
                        this.backgroundMiddleMiddle.linkedControl.style.height = r + "px",
                        this.backgroundMiddleRight.linkedControl.style.height = r + "px",
                        this.backgroundTopLeft.linkedControl.style.width = this.edgePixelsX + "px",
                        this.backgroundBottomLeft.linkedControl.style.width = this.edgePixelsX + "px",
                        this.backgroundMiddleLeft.linkedControl.style.width = this.edgePixelsX + "px",
                        this.backgroundTopRight.linkedControl.style.width = this.edgePixelsX + "px",
                        this.backgroundBottomRight.linkedControl.style.width = this.edgePixelsX + "px",
                        this.backgroundMiddleRight.linkedControl.style.width = this.edgePixelsX + "px",
                        this.backgroundTopMiddle.linkedControl.style.width = n + "px",
                        this.backgroundBottomMiddle.linkedControl.style.width = n + "px",
                        this.backgroundMiddleMiddle.linkedControl.style.width = n + "px",
                        this.backgroundTopLeft.linkedControl.style.left = e + "px",
                        this.backgroundBottomLeft.linkedControl.style.left = e + "px",
                        this.backgroundMiddleLeft.linkedControl.style.left = e + "px",
                        e += this.edgePixelsX,
                        this.backgroundTopMiddle.linkedControl.style.left = e + "px",
                        this.backgroundBottomMiddle.linkedControl.style.left = e + "px",
                        this.backgroundMiddleMiddle.linkedControl.style.left = e + "px",
                        e += n,
                        this.backgroundTopRight.linkedControl.style.left = e + "px",
                        this.backgroundBottomRight.linkedControl.style.left = e + "px",
                        this.backgroundMiddleRight.linkedControl.style.left = e + "px",
                        this.backgroundBottomLeft.linkedControl.style.bottom = t + "px",
                        this.backgroundBottomMiddle.linkedControl.style.bottom = t + "px",
                        this.backgroundBottomRight.linkedControl.style.bottom = t + "px",
                        t += this.edgePixelsY,
                        this.backgroundMiddleLeft.linkedControl.style.bottom = t + "px",
                        this.backgroundMiddleRight.linkedControl.style.bottom = t + "px",
                        this.backgroundMiddleMiddle.linkedControl.style.bottom = t + "px",
                        t += r,
                        this.backgroundTopLeft.linkedControl.style.bottom = t + "px",
                        this.backgroundTopMiddle.linkedControl.style.bottom = t + "px",
                        this.backgroundTopRight.linkedControl.style.bottom = t + "px"
                }
                this.backgroundLeft && this.backgroundRight && this.backgroundMiddle && (i -= 2 * this.edgePixelsX,
                    this.backgroundLeft.linkedControl.style.bottom = t + "px",
                    this.backgroundMiddle.linkedControl.style.bottom = t + "px",
                    this.backgroundRight.linkedControl.style.bottom = t + "px",
                    this.backgroundLeft.linkedControl.style.height = s + "px",
                    this.backgroundMiddle.linkedControl.style.height = s + "px",
                    this.backgroundRight.linkedControl.style.height = s + "px",
                    this.backgroundLeft.linkedControl.style.width = this.edgePixelsX + "px",
                    this.backgroundMiddle.linkedControl.style.width = i + "px",
                    this.backgroundRight.linkedControl.style.width = this.edgePixelsX + "px",
                    this.backgroundLeft.linkedControl.style.left = e + "px",
                    e += this.edgePixelsX,
                    this.backgroundMiddle.linkedControl.style.left = e + "px",
                    this.backgroundRight.linkedControl.style.left = e + i + "px")
            },
            p.prototype.setOpacity = function (e) {
                this.controlRect.linkedControl.style.opacity = e,
                    this.backgroundLeft && (this.backgroundLeft.linkedControl.style.opacity = e),
                    this.backgroundRight && (this.backgroundRight.linkedControl.style.opacity = e),
                    this.backgroundMiddle && (this.backgroundMiddle.linkedControl.style.opacity = e),
                    this.backgroundTopLeft && (this.backgroundTopLeft.linkedControl.style.opacity = e),
                    this.backgroundTopRight && (this.backgroundTopRight.linkedControl.style.opacity = e),
                    this.backgroundTopMiddle && (this.backgroundTopMiddle.linkedControl.style.opacity = e),
                    this.backgroundMiddleLeft && (this.backgroundMiddleLeft.linkedControl.style.opacity = e),
                    this.backgroundMiddleRight && (this.backgroundMiddleRight.linkedControl.style.opacity = e),
                    this.backgroundMiddleMiddle && (this.backgroundMiddleMiddle.linkedControl.style.opacity = e),
                    this.backgroundBottomLeft && (this.backgroundBottomLeft.linkedControl.style.opacity = e),
                    this.backgroundBottomRight && (this.backgroundBottomRight.linkedControl.style.opacity = e),
                    this.backgroundBottomMiddle && (this.backgroundBottomMiddle.linkedControl.style.opacity = e)
            },
            p.prototype.setBackgroundVisible = function (e) {
                this.backgroundLeft && this.backgroundLeft.showControl(e),
                    this.backgroundRight && this.backgroundRight.showControl(e),
                    this.backgroundMiddle && this.backgroundMiddle.showControl(e),
                    this.backgroundTopLeft && this.backgroundTopLeft.showControl(e),
                    this.backgroundTopRight && this.backgroundTopRight.showControl(e),
                    this.backgroundTopMiddle && this.backgroundTopMiddle.showControl(e),
                    this.backgroundMiddleLeft && this.backgroundMiddleLeft.showControl(e),
                    this.backgroundMiddleRight && this.backgroundMiddleRight.showControl(e),
                    this.backgroundMiddleMiddle && this.backgroundMiddleMiddle.showControl(e),
                    this.backgroundBottomLeft && this.backgroundBottomLeft.showControl(e),
                    this.backgroundBottomRight && this.backgroundBottomRight.showControl(e),
                    this.backgroundBottomMiddle && this.backgroundBottomMiddle.showControl(e)
            },
            p.prototype.setVisible = function (e) {
                this.controlRect.showControl(e),
                    this.setBackgroundVisible(e)
            },
            p.prototype.linkControl = function (e) {
                (this.controlRect.linkedControl = e).onmouseover = function () {
                        this.updateAlphas && (this.setOpacity(this.focusAlpha),
                            this.controlRect.mouseOver = !0,
                            this.linkedBackground && this.linkedBackground.setOpacity(this.focusAlpha))
                    }
                    .bind(this),
                    e.onmouseout = function () {
                        this.updateAlphas && (this.setOpacity(this.defaultAlpha),
                            this.controlRect.mouseOver = !1,
                            this.linkedBackground && this.linkedBackground.setOpacity(this.defaultAlpha))
                    }
                    .bind(this)
            },
            u.prototype.empty = function () {
                return this.bytes.length <= 0
            },
            u.prototype.readCString = function () {
                for (var e = this.bytes, t = e.length, i = 0; i < t; ++i)
                    if (0 == e[i])
                        return e = String.fromCharCode.apply(null, this.bytes.subarray(0, i)),
                            this.bytes = this.bytes.subarray(i + 1),
                            e;
                return null
            },
            u.prototype.asString = function () {
                for (var e = "", t = 0; t < this.bytes.length; ++t)
                    e += String.fromCharCode(this.bytes[t]);
                return e
            },
            u.prototype.readBytes = function (e) {
                var t = this.bytes.subarray(0, e);
                return this.bytes = this.bytes.subarray(e),
                    t
            },
            u.prototype.readUint32 = function () {
                var e = this.bytes,
                    t = e[0] | e[1] << 8 | e[2] << 16 | e[3] << 24;
                return this.bytes = e.subarray(4),
                    t
            },
            u.prototype.readUint8 = function () {
                var e = this.bytes,
                    t = e[0];
                return this.bytes = e.subarray(1),
                    t
            },
            u.prototype.readUint16 = function () {
                var e = this.bytes,
                    t = e[0] | e[1] << 8;
                return this.bytes = e.subarray(2),
                    t
            },
            u.prototype.readFloat32 = function () {
                var e = new Uint8Array(this.bytes);
                e = new Float32Array(e.buffer);
                return this.bytes = this.bytes.subarray(4),
                    e[0]
            },
            u.prototype.seekUint32 = function (e) {
                return (e = this.bytes.subarray(4 * e))[0] | e[1] << 8 | e[2] << 16 | e[3] << 24
            },
            u.prototype.seekFloat32 = function (e) {
                return e = new Uint8Array(this.bytes.subarray(4 * e)),
                    new Float32Array(e.buffer)[0]
            },
            u.prototype.getMatrix = function (e) {
                return new Float32Array(this.bytes.buffer, 64 * e, 16)
            },
            s.prototype.getScreenWidth = function () {
                if (this.linkedControl)
                    return this.guiScreen.width * this.getScreenWidthPercent()
            },
            s.prototype.getScreenHeight = function () {
                if (this.linkedControl)
                    return this.guiScreen.height * this.getScreenHeightPercent()
            },
            s.prototype.updateElement = function () {
                var e = this.linkedControl;
                if (e) {
                    var t = this.guiScreen.left * (1 - this.getScreenXPercent()),
                        i = this.guiScreen.bottom * (1 - this.getScreenYPercent()),
                        s = this.guiScreen.width * this.getScreenWidthPercent(),
                        n = this.guiScreen.height * this.getScreenHeightPercent();
                    e.style.left = t + "px",
                        e.style.bottom = i + "px",
                        e.style.width = s + "px",
                        e.style.height = n + "px"
                }
            },
            s.prototype.updateElement = function () {
                var e = this.linkedControl;
                if (e) {
                    var t = this.guiScreen.left * (1 - this.getScreenXPercent()),
                        i = this.guiScreen.bottom * (1 - this.getScreenYPercent()),
                        s = this.guiScreen.width * this.getScreenWidthPercent(),
                        n = this.guiScreen.height * this.getScreenHeightPercent();
                    e.style.left = t + "px",
                        e.style.bottom = i + "px",
                        e.style.width = s + "px",
                        e.style.height = n + "px"
                }
            },
            s.prototype.updateChildElements = function () {
                this.updateElement();
                for (var e = 0; e < this.childControlRects.length; e++)
                    this.childControlRects[e].updateChildElements()
            },
            s.prototype.set = function (e, t, i, s) {
                this.xPercent = e,
                    this.yPercent = t,
                    this.widthPercent = i,
                    this.heightPercent = s
            },
            s.prototype.linkControl = function (e) {
                (this.linkedControl = e).onmouseover = function () {
                        this.mouseOver = !0
                    }
                    .bind(this),
                    e.onmouseout = function () {
                        this.mouseOver = !1
                    }
                    .bind(this),
                    e.onmousedown = function () {
                        this.mouseDown = !0
                    }
                    .bind(this),
                    e.onmouseup = function () {
                        this.mouseDown = !1
                    }
                    .bind(this),
                    e.onclick = function () {
                        this.callBack && this.callBack(this),
                            this.clicked = !0
                    }
                    .bind(this)
            },
            s.prototype.showControl = function (e) {
                this.visible = e,
                    this.linkedControl && (this.linkedControl.style.display = e ? "block" : "none")
            },
            s.prototype.setOpacity = function (e) {
                this.opacity = e,
                    this.linkedControl && (this.linkedControl.style.opacity = e)
            },
            s.prototype.hasChildControlRect = function (e) {
                for (var t = 0; t < this.childControlRects.length; t++)
                    if (this.childControlRects[t] == e)
                        return !0;
                return !1
            },
            s.prototype.registerChildControlRect = function (e) {
                this.hasChildControlRect(e) || (this.childControlRects.push(e),
                    e.parentControlRect = this)
            },
            s.prototype.getScreenWidthPercent = function () {
                var e = this.widthPercent;
                return this.parentControlRect && (e *= this.parentControlRect.getScreenWidthPercent()),
                    e
            },
            s.prototype.getScreenHeightPercent = function () {
                var e = this.heightPercent;
                return this.parentControlRect && (e *= this.parentControlRect.getScreenHeightPercent()),
                    e
            },
            s.prototype.getScreenXPercent = function () {
                var e = this.xPercent;
                return this.parentControlRect && (e *= this.parentControlRect.getScreenWidthPercent(),
                        e += this.parentControlRect.getScreenXPercent()),
                    e
            },
            s.prototype.getScreenYPercent = function () {
                var e = this.yPercent;
                return this.parentControlRect && (e *= this.parentControlRect.getScreenHeightPercent(),
                        e += this.parentControlRect.getScreenYPercent()),
                    e
            };

        function n(e, t, i, s) {
            var n = !1,
                r = e + (-1 == e.indexOf("?") ? "?" : "&") + "thumb=1",
                a = function (e) {
                    return (e = new h(e).extract("thumbnail.jpg")) ? N.parseFile(e, t, s) : n ? i && i() : (n = !0,
                            C.fetchBinaryIncremental(r, a, i, 394240)),
                        0
                };
            C.fetchBinaryIncremental(r, a, i, 65536)
        }

        function f(e, t) {
            this.desc = t,
                this.gl = e,
                this.iblShader = e.shaderCache.fromURLs("fogvert.glsl", "fogfrag.glsl", ["#define FOG_IBL"]);
            var i = ["#define FOG_DIR"];
            this.dirShader = e.shaderCache.fromURLs("fogvert.glsl", "fogfrag.glsl", i),
                i.push("#define FOG_SHADOWS"),
                this.dirShaderShadow = e.shaderCache.fromURLs("fogvert.glsl", "fogfrag.glsl", i),
                i = ["#define FOG_SPOT"],
                this.spotShader = e.shaderCache.fromURLs("fogvert.glsl", "fogfrag.glsl", i),
                i.push("#define FOG_SHADOWS"),
                this.spotShaderShadow = e.shaderCache.fromURLs("fogvert.glsl", "fogfrag.glsl", i),
                i = ["#define FOG_OMNI"],
                this.omniShaderShadow = this.omniShader = e.shaderCache.fromURLs("fogvert.glsl", "fogfrag.glsl", i),
                this.fullscreenTriangle = e.createBuffer(),
                e.bindBuffer(e.ARRAY_BUFFER, this.fullscreenTriangle),
                i = new Float32Array([0, 0, 2, 0, 0, 2]),
                e.bufferData(e.ARRAY_BUFFER, i, e.STATIC_DRAW),
                e.bindBuffer(e.ARRAY_BUFFER, null)
        }

        function m(e, t) {
            this.gl = e,
                this.fbo = e.createFramebuffer(),
                e.bindFramebuffer(e.FRAMEBUFFER, this.fbo),
                t && (this.width = t.width,
                    this.height = t.height,
                    t.color0 && (this.color0 = t.color0,
                        e.framebufferTexture2D(e.FRAMEBUFFER, e.COLOR_ATTACHMENT0, e.TEXTURE_2D, this.color0.id, 0),
                        this.width = t.color0.desc.width,
                        this.height = t.color0.desc.height),
                    t.depth ? (this.depth = t.depth,
                        e.framebufferTexture2D(e.FRAMEBUFFER, e.DEPTH_ATTACHMENT, e.TEXTURE_2D, this.depth.id, 0)) : (this.depthBuffer = t.depthBuffer,
                        t.createDepth && !this.depthBuffer && (this.depthBuffer = m.createDepthBuffer(e, this.width, this.height)),
                        this.depthBuffer && (e.bindRenderbuffer(e.RENDERBUFFER, this.depthBuffer),
                            e.framebufferRenderbuffer(e.FRAMEBUFFER, e.DEPTH_ATTACHMENT, e.RENDERBUFFER, this.depthBuffer),
                            e.bindRenderbuffer(e.RENDERBUFFER, null)))),
                this.valid = t && t.ignoreStatus || e.checkFramebufferStatus(e.FRAMEBUFFER) == e.FRAMEBUFFER_COMPLETE,
                e.bindFramebuffer(e.FRAMEBUFFER, null)
        }
        (I = void 0 === I ? {} : I).embed = function (e, t) {
                var i, s = (t = function (e) {
                    if (e = e || {},
                        document.location.search)
                        for (var t = document.location.search.substring(1).split("&"), i = 0; i < t.length; ++i) {
                            var s = t[i].split("=");
                            e[s[0]] = s[1]
                        }
                    return t = function (e) {
                            if (0 | e)
                                return !0;
                            for (var t = "true True TRUE yes Yes YES".split(" "), i = 0; i < t.length; ++i)
                                if (e === t[i])
                                    return !0;
                            return !1
                        },
                        e.width = e.width || 800,
                        e.height = e.height || 600,
                        e.autoStart = t(e.autoStart),
                        e.pagePreset = t(e.pagePreset),
                        e.fullFrame = t(e.fullFrame) || t(e.bare),
                        e.fullFrame = !e.pagePreset && e.fullFrame,
                        e
                }(t)).thumbnailURL;
                if (t.pagePreset) {
                    i = new W(t.width, t.height, e, !!s),
                        document.body.style.backgroundColor = "#d7e4da";
                    var n = document.createElement("div");
                    n.style.position = "relative",
                        n.style.backgroundColor = "#e4e7e4",
                        n.style.width = t.width + 12 + "px",
                        n.style.height = t.height + 6 + 16 + "px",
                        n.style.margin = "auto",
                        n.style.boxShadow = "3px 5px 12px 0px grey",
                        document.body.appendChild(n);
                    var r = document.createElement("div");
                    if (r.style.position = "relative",
                        r.style.left = "6px",
                        r.style.top = "6px",
                        n.appendChild(r),
                        r.appendChild(i.domRoot),
                        !i.mobile) {
                        n.style.resize = "both",
                            n.style.overflow = "hidden";
                        var a = [n.style.width, n.style.height],
                            o = function () {
                                g.active() ? n.style.resize = "none" : (n.style.resize = "both",
                                        a[0] == n.style.width && a[1] == n.style.height || (a[0] = n.style.width,
                                            a[1] = n.style.height,
                                            i.resize(n.clientWidth - 12, n.clientHeight - 6 - 16))),
                                    window.setTimeout(o, 100)
                            };
                        o()
                    }
                } else
                    i = new W(t.fullFrame ? window.innerWidth : t.width, t.fullFrame ? window.innerHeight : t.height, e, !!s),
                    document.body.appendChild(i.domRoot),
                    t.fullFrame && (i.domRoot.style.position = "absolute",
                        i.domRoot.style.left = i.domRoot.style.top = 0,
                        window.addEventListener("resize", function () {
                            g.active() || i.resize(this.document.body.clientWidth, this.document.body.clientHeight)
                        }));
                return (webview = i).ui.setThumbnailURL(s),
                    t.autoStart && i.loadScene(),
                    i
            },
            I.fetchThumbnail = n,
            f.prototype.draw = function (e, t) {
                var i = this.gl,
                    s = e.view,
                    n = s.projectionMatrix,
                    r = S.empty();
                S.mul(r, s.viewMatrix, s.projectionMatrix),
                    S.invert(r, s.viewProjectionMatrix),
                    r = [n[10] + n[11], -n[14], -2 * n[11]],
                    n = [-2 / n[0], -2 / n[5], (1 - n[8]) / n[0], (1 - n[9]) / n[5]],
                    i.enable(i.BLEND),
                    i.blendFunc(i.ONE, i.ONE_MINUS_SRC_ALPHA);
                for (var a = 0; a < e.lights.count + 1; ++a) {
                    var o, h = a - 1,
                        l = h < e.lights.shadowCount;
                    (o = 0 == a ? this.iblShader : 0 < e.lights.spot[3 * h] ? l ? this.spotShaderShadow : this.spotShader : 0 < e.lights.getLightPos(h)[3] ? this.omniShader : l ? this.dirShaderShadow : this.dirShader).bind();
                    var d = o.params;
                    if (i.uniform3fv(d.uDepthToZ, r),
                        i.uniform4fv(d.uUnproject, n),
                        i.uniformMatrix4fv(d.uInvViewMatrix, !1, s.transform),
                        i.uniform1f(d.uFogInvDistance, 1 / this.desc.distance),
                        i.uniform1f(d.uFogOpacity, this.desc.opacity * (1 - e.stripData.activeFade())),
                        i.uniform1f(d.uFogDispersion, 1 - this.desc.dispersion),
                        (u = [0, 0, 0])[this.desc.type] = 1,
                        i.uniform3fv(d.uFogType, u),
                        i.uniform3fv(d.uFogColor, this.desc.color),
                        i.uniform1f(d.uFogIllum, 0 == a ? this.desc.skyIllum : this.desc.lightIllum),
                        i.uniformMatrix4fv(d.uLightMatrix, !1, e.lights.invMatrix),
                        0 == a) {
                        for (h = new Float32Array(e.sky.diffuseCoefficients),
                            l = 4; l < 16; ++l)
                            h[l] *= 1 - this.desc.dispersion;
                        for (l = 16; l < 36; ++l)
                            h[l] *= 1 - this.desc.dispersion * this.desc.dispersion;
                        i.uniform4fv(d.uFogLightSphere, h)
                    } else {
                        var c = e.lights.getLightPos(h),
                            u = (c = S.mul4(V.empty(), e.lights.invMatrix, c[0], c[1], c[2], c[3]),
                                e.lights.getLightDir(h));
                        u = S.mulVec(V.empty(), e.lights.invMatrix, u[0], u[1], u[2]);
                        i.uniform4fv(d.uLightPosition, c),
                            i.uniform3fv(d.uLightColor, e.lights.getColor(h));
                        c = .01745329251 * e.lights.spot[3 * h];
                        var f = Math.cos(.5 * c);
                        i.uniform4fv(d.uSpotParams, [-u[0], -u[1], -u[2], 0 < c ? f * f : 0]),
                            i.uniform4fv(d.uLightAttenuation, [e.lights.parameters[3 * h + 0], e.lights.parameters[3 * h + 1], e.lights.parameters[3 * h + 2], f]),
                            l && (l = S.mul(S.empty(), e.lights.finalTransformBuffer.subarray(16 * h), e.lights.matrix),
                                i.uniformMatrix4fv(d.uShadowProj, !1, l),
                                e.shadow.depthTextures[h].bind(o.samplers.uShadowMap),
                                h = 0,
                                1 < e.postRender.sampleCount && (h = e.postRender.currentSample() / e.postRender.sampleCount),
                                i.uniform1f(d.uDitherOffset, h),
                                i.uniform3fv(d.uAABBMin, e.bounds.min),
                                i.uniform3fv(d.uAABBMax, e.bounds.max),
                                h = V.lerp(V.empty(), e.bounds.min, e.bounds.max, .5),
                                l = V.distance(h, e.bounds.min),
                                i.uniform4f(d.uCylinder, h[0], h[1], h[2], l * l))
                    }
                    t.bind(o.samplers.tDepth),
                        o = o.attribs.vCoord,
                        i.bindBuffer(i.ARRAY_BUFFER, this.fullscreenTriangle),
                        i.enableVertexAttribArray(o),
                        i.vertexAttribPointer(o, 2, i.FLOAT, !1, 0, 0),
                        i.drawArrays(i.TRIANGLES, 0, 3),
                        i.disableVertexAttribArray(o),
                        i.bindBuffer(i.ARRAY_BUFFER, null)
                }
                i.disable(i.BLEND)
            },
            f.prototype.complete = function () {
                return this.iblShader.complete() && this.dirShader.complete() && this.dirShaderShadow.complete() && this.spotShader.complete() && this.spotShaderShadow.complete() && this.omniShader.complete() && this.omniShaderShadow.complete()
            },
            m.createDepthBuffer = function (e, t, i) {
                var s = e.createRenderbuffer();
                return e.bindRenderbuffer(e.RENDERBUFFER, s),
                    e.renderbufferStorage(e.RENDERBUFFER, e.DEPTH_COMPONENT16, t, i),
                    e.bindRenderbuffer(e.RENDERBUFFER, null),
                    s
            },
            m.prototype.bind = function () {
                this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this.fbo),
                    this.gl.viewport(0, 0, this.width, this.height)
            },
            m.bindNone = function (e) {
                e.bindFramebuffer(e.FRAMEBUFFER, null)
            };
        var g = {
            support: function () {
                return !!(document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled)
            },
            begin: function (e, t) {
                var i = e.requestFullscreen || e.webkitRequestFullScreen || e.mozRequestFullScreen || e.msRequestFullscreen;
                if (i) {
                    var s = function () {
                        g.active() || (document.removeEventListener("fullscreenchange", s),
                                document.removeEventListener("webkitfullscreenchange", s),
                                document.removeEventListener("mozfullscreenchange", s),
                                document.removeEventListener("MSFullscreenChange", s)),
                            t && t()
                    };
                    document.addEventListener("fullscreenchange", s),
                        document.addEventListener("webkitfullscreenchange", s),
                        document.addEventListener("mozfullscreenchange", s),
                        document.addEventListener("MSFullscreenChange", s),
                        i.bind(e)()
                }
            },
            end: function () {
                var e = document.exitFullscreen || document.webkitExitFullscreen || document.mozCancelFullScreen || document.msExitFullscreen;
                e && e.bind(document)()
            },
            active: function () {
                return !!(document.fullscreenElement || document.webkitIsFullScreen || document.mozFullScreenElement || document.msFullscreenElement)
            }
        };

        function v(e) {
            this.debugString = "GUIRegion",
                this.name = "Default",
                this.controlRect = new s(e),
                this.yPercent = this.xPercent = 0,
                this.heightPercent = this.widthPercent = 1,
                this.guiScreen = e
        }

        function t(e) {
            this.init = !1,
                this.ui = e,
                this.bottom = this.left = this.height = this.width = 0,
                this.clicked = this.mouseDown = !1,
                this.playbackControls = 0,
                e = 1,
                window.devicePixelRatio && (2 < window.devicePixelRatio ? e = 4 : 1 < window.devicePixelRatio && (e = 2)),
                this.imageSetNumber = e
        }

        function e(e) {
            this.onTap = [],
                this.onSingleTap = [],
                this.onDoubleTap = [],
                this.onDrag = [],
                this.onZoom = [],
                this.onPan = [],
                this.onPan2 = [],
                this.onAnything = [],
                this.mouseDownCount = 0,
                this.macHax = 0 <= navigator.platform.toUpperCase().indexOf("MAC"),
                e && this.attach(e)
        }

        function i(e, t) {
            e && t ? (this.frameIndex = t.frameIndex,
                this.value = t.value,
                this.interpolation = t.interpolation,
                this.weighIn = t.weighIn,
                this.weighOut = t.weighOut) : (this.interpolation = this.value = this.frameIndex = 0,
                this.weighOut = this.weighIn = 1)
        }

        function x(e, t) {
            for (var i in this.rotation = this.shadowCount = this.count = 0,
                    this.positions = [],
                    this.directions = [],
                    this.matrixWeights = [],
                    this.matrix = S.identity(),
                    this.invMatrix = S.identity(),
                    this.defaultmatrix = S.identity(),
                    this.defaultviewmatrix = S.identity(),
                    e)
                this[i] = e[i];
            this.count = this.positions.length / 4,
                this.count = Math.min(6, this.count),
                this.shadowCount = Math.min(3, this.shadowCount),
                this.positions = new Float32Array(this.positions),
                this.positionBuffer = new Float32Array(this.positions),
                this.directions = new Float32Array(this.directions),
                this.directionBuffer = new Float32Array(this.directions),
                this.colors = new Float32Array(this.colors),
                this.colorsBuffer = new Float32Array(this.colors),
                this.modelViewBuffer = new Float32Array(16 * this.shadowCount),
                this.projectionBuffer = new Float32Array(16 * this.shadowCount),
                this.finalTransformBuffer = new Float32Array(16 * this.shadowCount),
                this.inverseTransformBuffer = new Float32Array(16 * this.shadowCount),
                this.shadowTexelPadProjections = new Float32Array(4 * this.shadowCount),
                this.shadowsNeedUpdate = new Uint8Array(this.shadowCount);
            for (var s = 0; s < this.shadowsNeedUpdate.length; ++s)
                this.shadowsNeedUpdate[s] = 1;
            for (S.rotation(this.matrix, this.rotation, 1),
                S.transpose(this.invMatrix, this.matrix),
                S.copy(this.defaultmatrix, this.matrix),
                S.copy(this.defaultviewmatrix, t.viewMatrix),
                s = 0; s < this.count; ++s) {
                i = this.positions.subarray(4 * s, 4 * s + 4);
                var n = this.directions.subarray(3 * s, 3 * s + 3);
                1 == this.matrixWeights[s] ? (S.mul4(i, this.matrix, i[0], i[1], i[2], i[3]),
                    S.mulVec(n, this.matrix, n[0], n[1], n[2])) : 2 == this.matrixWeights[s] && (S.mul4(i, t.viewMatrix, i[0], i[1], i[2], i[3]),
                    S.mulVec(n, t.viewMatrix, n[0], n[1], n[2]))
            }
        }

        function y(e) {
            this.name = "none",
                this.text = "default text",
                this.title = "none",
                this.debugString = this.imagePath = "",
                this.controlRect = new s(e),
                this.textEntries = [],
                this.textOffsetsX = [],
                this.textOffsetsY = [],
                this.buttons = [],
                this.listBoxEntryHeight = 20,
                this.selectedItemText = "",
                this.selectedIndex = -1,
                this.localPixelsY = 0,
                this.localPixelsX = 100,
                this.labelPixelDrop = 0,
                this.labelPixelInset = 10,
                this.labelTextHeight = 16,
                this.closed = !1,
                this.defaultButtonText = this.spacerMiddle = this.spacerRight = this.spacerLeft = this.spacerControl = 0,
                this.listBoxButtons = [],
                this.listBoxRegion = new v(e),
                this.guiScreen = e,
                this.lastMouseOverIndex = -1,
                this.selectionChangedCallback = 0,
                this.debugString = ""
        }

        function b(e, t, i) {
            this.gl = e,
                this.name = i.name;
            var s = {
                    mipmap: !0,
                    aniso: e.hints.mobile ? 0 : 4,
                    clamp: !!i.textureWrapClamp,
                    mirror: !!i.textureWrapMirror
                },
                n = {
                    mipmap: s.mipmap,
                    clamp: s.clamp,
                    mirror: s.mirror,
                    nofilter: i.textureFilterNearest || !1
                };
            if (n.nofilter || (n.aniso = e.hints.mobile ? 2 : 4),
                this.textures = {
                    albedo: e.textureCache.fromFilesMergeAlpha(t.get(i.albedoTex), t.get(i.alphaTex), n),
                    reflectivity: e.textureCache.fromFilesMergeAlpha(t.get(i.reflectivityTex), t.get(i.glossTex), s),
                    normal: e.textureCache.fromFile(t.get(i.normalTex), s),
                    extras: e.textureCache.fromFilesMergeAlpha(t.get(i.extrasTex), t.get(i.extrasTexA), s)
                },
                this.extrasTexCoordRanges = {},
                i.extrasTexCoordRanges)
                for (var r in i.extrasTexCoordRanges)
                    this.extrasTexCoordRanges[r] = new Float32Array(i.extrasTexCoordRanges[r].scaleBias);
            this.textures.extras || ((t = new U(e, {
                    width: 1,
                    height: 1
                })).loadArray(new Uint8Array([255, 255, 255, 255])),
                this.textures.extras = t);
            var a = i.blendTint || [1, 1, 1];
            t = {
                    none: function () {
                        e.disable(e.BLEND)
                    },
                    alpha: function () {
                        e.enable(e.BLEND),
                            e.blendFuncSeparate(e.SRC_ALPHA, e.ONE_MINUS_SRC_ALPHA, e.ONE_MINUS_DST_ALPHA, e.ONE)
                    },
                    add: function () {
                        e.enable(e.BLEND),
                            e.blendColor(a[0], a[1], a[2], 1),
                            e.blendFunc(e.ONE, e.CONSTANT_COLOR)
                    }
                },
                this.blend = t[i.blend] || t.none,
                this.alphaTest = i.alphaTest || 0,
                this.usesBlending = this.blend !== t.none,
                this.usesRefraction = !!i.refraction,
                this.shadowAlphaTest = this.alphaTest,
                this.shadowAlphaTest <= 0 && this.blend === t.alpha && (this.shadowAlphaTest = .5),
                this.castShadows = this.blend !== t.add,
                this.horizonOcclude = i.horizonOcclude || 0,
                this.fresnel = new Float32Array(i.fresnel ? i.fresnel : [1, 1, 1]),
                this.emissiveIntensity = i.emissiveIntensity || 1,
                n = !(s = []),
                0 < i.lightCount && s.push("#define LIGHT_COUNT " + i.lightCount),
                0 < i.shadowCount && (r = Math.min(i.lightCount, i.shadowCount),
                    this.usesRefraction && e.limits.textureCount <= 8 && (r = 2 < r ? 2 : r),
                    s.push("#define SHADOW_COUNT " + r)),
                0 < i.alphaTest && s.push("#define ALPHA_TEST"),
                this.blend === t.alpha ? s.push("#define TRANSPARENCY_DITHER") : this.blend === t.none && s.push("#define NOBLEND"),
                e.hints.mobile && s.push("#define MOBILE"),
                e.ext.textureDepth && s.push("#define SHADOW_NATIVE_DEPTH"),
                r = function (e) {
                    return 1 / (2 / 3 * 3.1415962 * (e * e + e + 1))
                },
                i.useSkin && (s.push("#define SKIN"),
                    this.skinParams = i.skinParams || {
                        subdermisColor: [1, 1, 1],
                        transColor: [1, 0, 0, 1],
                        fresnelColor: [.2, .2, .2, .5],
                        fresnelOcc: 1,
                        fresnelGlossMask: 1,
                        transSky: .5,
                        shadowBlur: .5,
                        normalSmooth: .5,
                        transScatter: 0,
                        transDepth: 0,
                        millimeterScale: 1
                    },
                    this.extrasTexCoordRanges.subdermisTex || s.push("#define SKIN_NO_SUBDERMIS_TEX"),
                    this.extrasTexCoordRanges.translucencyTex || s.push("#define SKIN_NO_TRANSLUCENCY_TEX"),
                    this.extrasTexCoordRanges.fuzzTex || s.push("#define SKIN_NO_FUZZ_TEX"),
                    void 0 === this.skinParams.version && (this.skinParams.version = 1),
                    2 == this.skinParams.version ? (s.push("#define SKIN_VERSION_2"),
                        this.skinParams.shadowBlur *= 4,
                        this.skinParams.shadowBlur = Math.min(this.skinParams.shadowBlur, 40),
                        this.skinParams.transIntegral = r(.5 * this.skinParams.transScatter),
                        this.skinParams.fresnelIntegral = 1 / 3.14159 * (1 - .5 * this.skinParams.fresnelColor[3]),
                        this.skinParams.transSky = 0) : (s.push("#define SKIN_VERSION_1"),
                        this.skinParams.shadowBlur = 8 * Math.min(this.skinParams.shadowBlur, 1),
                        this.skinParams.transDepth = 0,
                        this.skinParams.transScatter = this.skinParams.transColor[3],
                        this.skinParams.transIntegral = 1 / 3.14159 * (1 - .5 * this.skinParams.transScatter),
                        this.skinParams.fresnelIntegral = 1 / 3.14159 * (1 - .5 * this.skinParams.fresnelColor[3]),
                        this.skinParams.transSky *= 1.25,
                        this.skinParams.transIntegral *= 1.25)),
                i.aniso && (s.push("#define ANISO"),
                    this.anisoParams = i.anisoParams || {
                        strength: 1,
                        tangent: [1, 0, 0],
                        integral: .5
                    },
                    this.extrasTexCoordRanges.anisoTex || s.push("#define ANISO_NO_DIR_TEX")),
                i.microfiber && (s.push("#define MICROFIBER"),
                    this.microfiberParams = i.microfiberParams || {
                        fresnelColor: [.2, .2, .2, .5],
                        fresnelOcc: 1,
                        fresnelGlossMask: 1
                    },
                    this.microfiberParams.fresnelIntegral = 1 / 3.14159 * (1 - .5 * this.microfiberParams.fresnelColor[3]),
                    this.extrasTexCoordRanges.fuzzTex || s.push("#define MICROFIBER_NO_FUZZ_TEX")),
                i.refraction && (s.push("#define REFRACTION"),
                    this.refractionParams = i.refractionParams || {
                        distantBackground: !1,
                        tint: [1, 1, 1],
                        useAlbedoTint: !1,
                        IOR: 1.5
                    },
                    this.extrasTexCoordRanges.refractionMaskTex || s.push("#define REFRACTION_NO_MASK_TEX")),
                i.vertexColor && (s.push("#define VERTEX_COLOR"),
                    i.vertexColorsRGB && s.push("#define VERTEX_COLOR_SRGB"),
                    i.vertexColorAlpha && s.push("#define VERTEX_COLOR_ALPHA")),
                this.horizonSmoothing = i.horizonSmoothing || 0,
                0 < this.horizonSmoothing && s.push("#define HORIZON_SMOOTHING"),
                i.unlitDiffuse && s.push("#define DIFFUSE_UNLIT"),
                this.extrasTexCoordRanges.emissiveTex && (s.push("#define EMISSIVE"),
                    i.emissiveSecondaryUV && (s.push("#define EMISSIVE_SECONDARY_UV"),
                        n = !0)),
                this.extrasTexCoordRanges.aoTex && (s.push("#define AMBIENT_OCCLUSION"),
                    i.aoSecondaryUV && (s.push("#define AMBIENT_OCCLUSION_SECONDARY_UV"),
                        n = !0)),
                i.tangentOrthogonalize && s.push("#define TSPACE_ORTHOGONALIZE"),
                i.tangentNormalize && s.push("#define TSPACE_RENORMALIZE"),
                i.tangentGenerateBitangent && s.push("#define TSPACE_COMPUTE_BITANGENT"),
                n && s.push("#define TEXCOORD_SECONDARY"),
                this.vOffset = this.uOffset = 0,
                s.push("#define UV_OFFSET "),
                this.shader = e.shaderCache.fromURLs("matvert.glsl", "matfrag.glsl", s),
                s.push("#define STRIPVIEW"),
                this.stripShader = e.shaderCache.fromURLs("matvert.glsl", "matfrag.glsl", s),
                this.wireShader = e.shaderCache.fromURLs("wirevert.glsl", "wirefrag.glsl"),
                this.blend === t.alpha && (this.prepassShader = e.shaderCache.fromURLs("alphaprepassvert.glsl", "alphaprepassfrag.glsl"))
        }
        v.prototype.addImageElement = function (e, t) {
                var i = this.guiScreen.ui.menuCluster.contents,
                    s = document.createElement("input");
                e.linkControl(s),
                    this.guiScreen.updateElement(e),
                    s.type = "image",
                    s.src = I.dataLocale + t,
                    s.style.position = "absolute",
                    s.style.border = "none",
                    s.style.outline = "0px",
                    s.style.zIndex = "1",
                    s.title = t,
                    s.style.opacity = e.opacity;
                var n = new XMLHttpRequest();
                return n.open("HEAD", s.src, !0),
                    n.onload = function (e) {
                        e.appendChild(this)
                    }
                    .bind(s, i),
                    n.send(),
                    s
            },
            v.prototype.addImage = function (e) {
                var t = new s(this.guiScreen);
                return this.addImageElement(t, e),
                    t
            },
            v.prototype.addTextButton = function (e, t, i, s, n, r) {
                var a = new p(this.guiScreen);
                return a.name = "none",
                    a.text = e,
                    a.controlRect.set(t, i, s, n),
                    a.controlRect.opacity = r,
                    this.controlRect.registerChildControlRect(a.controlRect),
                    t = this.guiScreen.ui.menuCluster.contents,
                    (i = document.createElement("text")).style.color = "white",
                    i.style.fontFamily = "Arial",
                    i.style.fontSize = I.largeUI ? "14px" : "12px",
                    i.style.textShadow = "2px 2px 3px #000000",
                    t.appendChild(i),
                    a.controlRect.linkControl(i),
                    this.guiScreen.updateElement(a.controlRect),
                    i.type = "text",
                    i.name = "text",
                    i.style.position = "absolute",
                    i.style.border = "none",
                    i.style.outline = "0px",
                    i.style.zIndex = "2",
                    i.innerHTML = e,
                    i.style.opacity = a.controlRect.opacity,
                    a.linkControl(i),
                    a
            },
            t.prototype.setSize = function (e, t) {
                this.width = e,
                    this.height = t,
                    this.left = -e,
                    this.bottom = -t,
                    this.playbackControls && this.playbackControls.resize(this)
            },
            t.prototype.setupActiveView = function (e) {
                this.init || (this.init = !0,
                    (this.ui = e).viewer.scene.sceneAnimator && (this.playbackControls = new R(this),
                        this.playbackControls.resize(this)))
            },
            t.prototype.updateElement = function (e) {
                var t = e.linkedControl;
                if (t) {
                    var i = this.left * (1 - e.getScreenXPercent()),
                        s = this.bottom * (1 - e.getScreenYPercent()),
                        n = this.width * e.getScreenWidthPercent();
                    e = this.height * e.getScreenHeightPercent(),
                        t.style.left = i + "px",
                        t.style.bottom = s + "px",
                        t.style.width = n + "px",
                        t.style.height = e + "px"
                }
            },
            e.prototype.attach = function (e) {
                this.element = e;
                var m = function (e) {
                        for (var t = 0; t < this.onAnything.length; ++t)
                            this.onAnything[t]();
                        e.preventDefault()
                    }
                    .bind(this);
                this.mouseStates = [{
                        pressed: !1,
                        position: [0, 0],
                        downPosition: [0, 0]
                    }, {
                        pressed: !1,
                        position: [0, 0],
                        downPosition: [0, 0]
                    }, {
                        pressed: !1,
                        position: [0, 0],
                        downPosition: [0, 0]
                    }],
                    this.lastTapPos = [0, 0],
                    e = function (e) {
                        if (e.target === this.element) {
                            this.mouseDownCount++;
                            var t = this.mouseStates[e.button];
                            if (t) {
                                t.pressed = !0;
                                var i = this.element.getBoundingClientRect();
                                t.position[0] = t.downPosition[0] = e.clientX - i.left,
                                    t.position[1] = t.downPosition[1] = e.clientY - i.top,
                                    m(e)
                            }
                        }
                    }
                    .bind(this),
                    this.element.addEventListener("mousedown", e),
                    e = function (e) {
                        var t = this.mouseStates[e.button];
                        if (t) {
                            var i = this.element.getBoundingClientRect(),
                                s = e.clientX - i.left;
                            i = e.clientY - i.top;
                            if (t.pressed = !1,
                                t.position[0] = s,
                                t.position[1] = i,
                                0 == e.button && e.target == this.element && Math.abs(t.position[0] - t.downPosition[0]) + Math.abs(t.position[1] - t.downPosition[1]) < 10) {
                                for (var n = 0; n < this.onTap.length; ++n)
                                    this.onTap[n](s, i);
                                if (this.needSingleClick = !0,
                                    window.setTimeout(function (e, t) {
                                            if (this.needSingleClick) {
                                                for (var i = 0; i < this.onSingleTap.length; ++i)
                                                    this.onSingleTap[i](e, t);
                                                this.needSingleClick = !1
                                            }
                                        }
                                        .bind(this, s, i), 301),
                                    t = !1,
                                    void 0 !== this.doubleClickTimer && (n = Math.abs(s - this.lastTapPos[0]) + Math.abs(i - this.lastTapPos[1]) < 8,
                                        Date.now() - this.doubleClickTimer < 300 && n))
                                    for (t = !0,
                                        this.needSingleClick = !1,
                                        n = 0; n < this.onDoubleTap.length; ++n)
                                        this.onDoubleTap[n](s, i);
                                this.doubleClickTimer = Date.now(),
                                    t && (this.doubleClickTimer = -1e9),
                                    this.lastTapPos[0] = s,
                                    this.lastTapPos[1] = i
                            }
                        }
                        m(e)
                    }
                    .bind(this),
                    this.element.addEventListener("mouseup", e),
                    e = function (e) {
                        for (var t = !1, i = this.element.getBoundingClientRect(), s = 0; s < 3; ++s) {
                            var n = this.mouseStates[s];
                            if (n.pressed) {
                                webview.stopRotate();
                                t = e.clientX - i.left;
                                var r = e.clientY - i.top,
                                    a = t - n.position[0],
                                    o = r - n.position[1];
                                if (n.position[0] = t,
                                    n.position[1] = r,
                                    2 == s && e.altKey)
                                    for (n = 0; n < this.onZoom.length; ++n)
                                        this.onZoom[n](2 * o);
                                else if (1 <= s || e.ctrlKey)
                                    for (n = 0; n < this.onPan.length; ++n)
                                        this.onPan[n](a, o);
                                else if (0 == s)
                                    if (e.shiftKey)
                                        for (n = 0; n < this.onPan2.length; ++n)
                                            this.onPan2[n](a, o);
                                    else
                                        for (n = 0; n < this.onDrag.length; ++n)
                                            this.onDrag[n](t, r, a, o);
                                t = !0
                            }
                        }
                        t && m(e)
                    }
                    .bind(this),
                    this.element.addEventListener("mousemove", e),
                    e = function (e) {
                        var t = 0;
                        e.deltaY ? (t = -.4 * e.deltaY,
                            1 == e.deltaMode ? t *= 16 : 2 == e.deltaMode && (t *= this.element.clientHeight)) : e.wheelDelta ? t = this.macHax && 120 == Math.abs(e.wheelDelta) ? .08 * e.wheelDelta : .4 * e.wheelDelta : e.detail && (t = -10 * e.detail);
                        for (var i = 0; i < this.onZoom.length; ++i)
                            this.onZoom[i](t);
                        m(e)
                    }
                    .bind(this),
                    this.element.addEventListener("mousewheel", e),
                    this.element.addEventListener("DOMMouseScroll", e),
                    this.element.addEventListener("wheel", e),
                    e = function (e) {
                        for (var t = 0; t < this.mouseStates.length; ++t)
                            this.mouseStates[t].pressed = !1;
                        e.preventDefault()
                    }
                    .bind(this),
                    this.element.addEventListener("mouseleave", e),
                    this.element.addEventListener("contextmenu", function (e) {
                        e.preventDefault()
                    }),
                    this.touches = {},
                    this.tapPossible = !1,
                    this.touchCountFloor = 0,
                    e = function (e) {
                        for (var t = this.element.getBoundingClientRect(), i = !1, s = 0; s < e.changedTouches.length; ++s)
                            if (e.target === this.element) {
                                var n = e.changedTouches[s];
                                (i = {
                                    x: n.clientX - t.left,
                                    y: n.clientY - t.top
                                }).startX = i.x,
                                    i.startY = i.y,
                                    this.touches[n.identifier] = i,
                                    i = !0
                            }
                        for (this.tapPossible = 1 == e.touches.length,
                            n = t = 0; n < this.touches.length; ++n)
                            t++;
                        t > this.touchCountFloor && (this.touchCountFloor = t),
                            i && m(e)
                    }
                    .bind(this),
                    this.element.addEventListener("touchstart", e),
                    e = function (e) {
                        for (var t = !1, i = 0; i < e.changedTouches.length; ++i) {
                            var s = e.changedTouches[i],
                                n = this.touches[s.identifier];
                            if (n) {
                                if (this.tapPossible) {
                                    var r = this.element.getBoundingClientRect();
                                    t = s.clientX - r.left,
                                        r = s.clientY - r.top;
                                    if (Math.max(Math.abs(t - n.startX), Math.abs(r - n.startY)) < 24) {
                                        for (i = 0; i < this.onTap.length; ++i)
                                            this.onTap[i](t, r);
                                        if (this.needSingleTap = !0,
                                            window.setTimeout(function (e, t) {
                                                    if (this.needSingleTap) {
                                                        for (var i = 0; i < this.onSingleTap.length; ++i)
                                                            this.onSingleTap[i](e, t);
                                                        this.needSingleTap = !1
                                                    }
                                                }
                                                .bind(this, t, r), 501),
                                            n = !1,
                                            void 0 !== this.doubleTapTimer) {
                                            var a = Math.max(Math.abs(t - this.lastTapPos[0]), Math.abs(r - this.lastTapPos[1])) < 24,
                                                o = Date.now() - this.doubleTapTimer < 500;
                                            if (a && o)
                                                for (n = !0,
                                                    i = 0; i < this.onDoubleTap.length; ++i)
                                                    this.onDoubleTap[i](t, r)
                                        }
                                        this.doubleTapTimer = Date.now(),
                                            n && (this.doubleTapTimer = -1e9),
                                            this.lastTapPos[0] = t,
                                            this.lastTapPos[1] = r
                                    }
                                    this.tapPossible = !1
                                }
                                delete this.touches[s.identifier],
                                    t = !0
                            }
                        }
                        for (s = i = 0; s < this.touches.length; ++s)
                            i++;
                        i <= 0 && (this.touchCountFloor = 0),
                            t && m(e)
                    }
                    .bind(this),
                    this.element.addEventListener("touchend", e),
                    this.element.addEventListener("touchcancel", e),
                    this.element.addEventListener("touchleave", e),
                    e = function (e) {
                        webview.stopRotate();
                        for (var t = [], i = 0; i < e.touches.length; ++i)
                            e.touches[i].target === this.element && t.push(e.touches[i]);
                        var s = this.element.getBoundingClientRect();
                        if (1 == t.length && this.touchCountFloor <= 1) {
                            var n = t[0],
                                r = this.touches[n.identifier];
                            if (r) {
                                var a = n.clientX - s.left,
                                    o = (n = n.clientY - s.top,
                                        s = a - r.x,
                                        n - r.y);
                                for (r.x = a,
                                    r.y = n,
                                    i = 0; i < this.onDrag.length; ++i)
                                    this.onDrag[i](a, n, s, o, e.shiftKey)
                            }
                        } else if (2 == t.length && this.touchCountFloor <= 2) {
                            if (o = t[0],
                                i = this.touches[o.identifier],
                                n = t[1],
                                r = this.touches[n.identifier],
                                i && r) {
                                a = o.clientX - s.left,
                                    o = o.clientY - s.top;
                                var h = n.clientX - s.left,
                                    l = n.clientY - s.top,
                                    d = Math.sqrt((a - h) * (a - h) + (o - l) * (o - l)),
                                    c = Math.sqrt((i.x - r.x) * (i.x - r.x) + (i.y - r.y) * (i.y - r.y)),
                                    u = Math.abs(d - c),
                                    f = (s = (a - i.x + h - r.x) / 2,
                                        n = (o - i.y + l - r.y) / 2,
                                        Math.sqrt(s * s + n * n));
                                if (i.x = a,
                                    i.y = o,
                                    r.x = h,
                                    r.y = l,
                                    0 < u)
                                    for (r = u / (u + f),
                                        i = 0; i < this.onZoom.length; ++i)
                                        this.onZoom[i](2 * (d - c) * r);
                                if (0 < f)
                                    for (r = f / (u + f),
                                        i = 0; i < this.onDrag.length; ++i)
                                        this.onPan[i](s * r, n * r)
                            }
                        } else if (3 <= t.length) {
                            for (i = c = d = h = o = 0; i < t.length; ++i)
                                n = t[i],
                                r = this.touches[n.identifier],
                                d += a = n.clientX - s.left,
                                c += n = n.clientY - s.top,
                                r && (o += r.x,
                                    h += r.y,
                                    r.x = a,
                                    r.y = n);
                            for (o /= t.length,
                                h /= t.length,
                                d /= t.length,
                                c /= t.length,
                                i = 0; i < this.onPan2.length; ++i)
                                this.onPan2[i](d - o, c - h)
                        }
                        0 < t.length && m(e)
                    }
                    .bind(this),
                    this.element.addEventListener("touchmove", e)
            },
            x.prototype.getLightPos = function (e) {
                return this.positionBuffer.subarray(4 * e, 4 * e + 4)
            },
            x.prototype.setLightDistance = function (e, t) {
                t <= 0 && (t = 1e-5),
                    this.parameters[3 * e + 2] = 1 / t
            },
            x.prototype.setLightSpotAngle = function (e, t) {
                t <= 0 && (t = 1e-6),
                    this.spot[3 * e] = t;
                var i = Math.sin(3.1415926 / 180 * t / 2);
                this.spot[3 * e + 2] = 1 / (i * i) * this.spot[3 * e + 1]
            },
            x.prototype.setLightSpotSharpness = function (e, t) {
                this.spot[3 * e + 1] = t,
                    this.setLightSpotAngle(this.spot[3 * e])
            },
            x.prototype.setLightPos = function (e, t) {
                this.positions[4 * e + 0] = t[0],
                    this.positions[4 * e + 1] = t[1],
                    this.positions[4 * e + 2] = t[2];
                var i = this.positions.subarray(4 * e, 4 * e + 4);
                1 == this.matrixWeights[e] ? S.mul4(i, this.defaultmatrix, t[0], t[1], t[2], i[3]) : 2 == this.matrixWeights[e] && S.mul4(i, this.defaultviewmatrix, t[0], t[1], t[2], i[3])
            },
            x.prototype.setLightDir = function (e, t) {
                this.directions[3 * e + 0] = t[0],
                    this.directions[3 * e + 1] = t[1],
                    this.directions[3 * e + 2] = t[2];
                var i = this.directions.subarray(3 * e, 3 * e + 3);
                1 == this.matrixWeights[e] ? S.mulVec(i, this.defaultmatrix, t[0], t[1], t[2]) : 2 == this.matrixWeights[e] && S.mulVec(i, this.defaultviewmatrix, t[0], t[1], t[2])
            },
            x.prototype.getLightColor = function (e) {
                return this.colors.subarray(3 * e, 3 * e + 3)
            },
            x.prototype.setLightColor = function (e, t) {
                this.colors[3 * e + 0] = t[0],
                    this.colors[3 * e + 1] = t[1],
                    this.colors[3 * e + 2] = t[2]
            },
            x.prototype.getLightDir = function (e) {
                return this.directionBuffer.subarray(3 * e, 3 * e + 3)
            },
            x.prototype.getColor = function (e) {
                return e *= 3,
                    [this.colors[e], this.colors[e + 1], this.colors[e + 2]]
            },
            x.prototype.update = function (e, t) {
                var i = new S.type(this.matrix);
                S.rotation(this.matrix, this.rotation, 1),
                    S.transpose(this.invMatrix, this.matrix);
                for (var s = 0; s < this.count; ++s) {
                    var n = this.positions.subarray(4 * s, 4 * s + 4),
                        r = this.directions.subarray(3 * s, 3 * s + 3),
                        a = this.getLightPos(s),
                        o = this.getLightDir(s);
                    1 == this.matrixWeights[s] ? (a[0] = n[0],
                            a[1] = n[1],
                            a[2] = n[2],
                            a[3] = n[3],
                            o[0] = r[0],
                            o[1] = r[1],
                            o[2] = r[2]) : 2 == this.matrixWeights[s] ? (S.mul4(a, e.transform, n[0], n[1], n[2], n[3]),
                            S.mulVec(o, e.transform, r[0], r[1], r[2]),
                            S.mul4(a, this.matrix, a[0], a[1], a[2], a[3]),
                            S.mulVec(o, this.matrix, o[0], o[1], o[2])) : (S.mul4(a, this.matrix, n[0], n[1], n[2], n[3]),
                            S.mulVec(o, this.matrix, r[0], r[1], r[2])),
                        V.normalize(o, o)
                }
                r = new Float32Array(this.finalTransformBuffer),
                    a = S.empty(),
                    o = S.empty();
                var h = S.empty(),
                    l = V.empty(),
                    d = V.empty(),
                    c = V.empty(),
                    u = V.empty(),
                    f = (n = V.empty(),
                        []),
                    m = [],
                    p = S.create(.5, 0, 0, .5, 0, .5, 0, .5, 0, 0, .5, .5, 0, 0, 0, 1);
                for (s = 0; s < this.count; ++s) {
                    for (l = this.getLightPos(s),
                        d = this.getLightDir(s),
                        .99 < Math.abs(d[1]) ? V.set(c, 1, 0, 0) : V.set(c, 0, 1, 0),
                        V.cross(u, c, d),
                        V.normalize(u, u),
                        V.cross(c, d, u),
                        V.normalize(c, c),
                        S.set(a, u[0], u[1], u[2], -V.dot(u, l), c[0], c[1], c[2], -V.dot(c, l), d[0], d[1], d[2], -V.dot(d, l), 0, 0, 0, 1),
                        l = 0; l < 8; ++l)
                        n[0] = 1 & l ? t.max[0] : t.min[0],
                        n[1] = 2 & l ? t.max[1] : t.min[1],
                        n[2] = 4 & l ? t.max[2] : t.min[2],
                        S.mulPoint(n, this.matrix, 1.005 * n[0], 1.005 * n[1], 1.005 * n[2]),
                        S.mulPoint(n, a, n[0], n[1], n[2]),
                        0 == l ? (f[0] = m[0] = n[0],
                            f[1] = m[1] = n[1],
                            f[2] = m[2] = n[2]) : (f[0] = Math.min(f[0], n[0]),
                            f[1] = Math.min(f[1], n[1]),
                            f[2] = Math.min(f[2], n[2]),
                            m[0] = Math.max(m[0], n[0]),
                            m[1] = Math.max(m[1], n[1]),
                            m[2] = Math.max(m[2], n[2]));
                    l = -f[2],
                        d = -m[2];
                    var g = this.spot[3 * s];
                    0 < g ? (l = Math.min(l, 1 / this.parameters[3 * s + 2]),
                            d = Math.max(.04 * l, d),
                            S.perspective(o, g, 1, d, l),
                            s < this.shadowCount && (l = 2 * -Math.tan(.00872664625 * g),
                                this.shadowTexelPadProjections[4 * s + 0] = this.modelViewBuffer[16 * s + 2] * l,
                                this.shadowTexelPadProjections[4 * s + 1] = this.modelViewBuffer[16 * s + 6] * l,
                                this.shadowTexelPadProjections[4 * s + 2] = this.modelViewBuffer[16 * s + 10] * l,
                                this.shadowTexelPadProjections[4 * s + 3] = this.modelViewBuffer[16 * s + 14] * l)) : (S.ortho(o, f[0], m[0], f[1], m[1], d, l),
                            s < this.shadowCount && (this.shadowTexelPadProjections[4 * s + 0] = this.shadowTexelPadProjections[4 * s + 1] = this.shadowTexelPadProjections[4 * s + 2] = 0,
                                this.shadowTexelPadProjections[4 * s + 3] = Math.max(m[0] - f[0], m[1] - f[1]))),
                        S.mul(h, o, a),
                        S.mul(h, p, h),
                        S.copyToBuffer(this.modelViewBuffer, 16 * s, a),
                        S.copyToBuffer(this.projectionBuffer, 16 * s, o),
                        S.copyToBuffer(this.finalTransformBuffer, 16 * s, h),
                        S.invert(h, h),
                        S.copyToBuffer(this.inverseTransformBuffer, 16 * s, h)
                }
                for (n = !1,
                    s = 0; s < i.length; ++s)
                    if (i[s] != this.matrix[s]) {
                        n = !0;
                        break
                    }
                for (s = 0; s < this.shadowCount; s++)
                    if (n && 1 == this.matrixWeights[s])
                        this.shadowsNeedUpdate[s] = 1;
                    else
                        for (i = 16 * s; i < 16 * s + 16; ++i)
                            if (r[i] != this.finalTransformBuffer[i]) {
                                this.shadowsNeedUpdate[s] = 1;
                                break
                            }
            },
            x.prototype.flagUpdateAnimatedLighting = function () {
                for (var e = 0; e < this.shadowCount; e++)
                    this.shadowsNeedUpdate[e] = 1
            },
            y.prototype.linkControl = function (e) {
                this.controlRect.linkControl(e)
            },
            y.prototype.spawnControl = function (e, t, i, s, n, r) {
                var a = "backgroundTopLE" + (w = this.guiScreen.imageSetNumber) + "x.png",
                    o = "backgroundTopM" + w + "x.png",
                    h = "backgroundTopRE" + w + "x.png",
                    l = "backgroundMiddleLE" + w + "x.png",
                    d = "backgroundMiddleM" + w + "x.png",
                    c = "backgroundMiddleRE" + w + "x.png",
                    u = "backgroundBottomLE" + w + "x.png",
                    f = "backgroundBottomM" + w + "x.png",
                    m = "backgroundBottomRE" + w + "x.png",
                    p = 3 * w,
                    g = "backgroundLE" + w + "x.png",
                    v = "backgroundM" + w + "x.png",
                    x = "backgroundRE" + w + "x.png",
                    y = 2 * w,
                    b = "spacerLE" + w + "x.png",
                    S = "spacerM" + w + "x.png",
                    T = "spacerRE" + w + "x.png",
                    w = 2 * w,
                    C = this.controlRect.guiScreen.width,
                    R = this.controlRect.guiScreen.height;
                if (n) {
                    n = this.textEntries.length;
                    var A = i;
                    for (i = 0; i < n; i++) {
                        var k = 8 * (this.textEntries[i] ? this.textEntries[i].length : 0);
                        A < k && (A = k)
                    }
                    i = A + r
                }
                for (r = 1 / (n = this.textEntries.length + 1),
                    this.localPixelsX = i,
                    this.listBoxEntryHeight = s,
                    this.localPixelsY = (this.textEntries.length + 1) * this.listBoxEntryHeight,
                    i = 8 / this.localPixelsY,
                    s = 6 / this.localPixelsX,
                    A = 4 / this.localPixelsX,
                    k = r - i / 4,
                    this.labelTextHeight = I.largeUI ? 20 : 16,
                    this.labelPixelDrop = (this.listBoxEntryHeight - this.labelTextHeight) / 2,
                    this.listBoxRegion.controlRect.widthPercent = this.localPixelsX / C,
                    this.listBoxRegion.controlRect.heightPercent = this.localPixelsY / R,
                    this.listBoxRegion.controlRect.xPercent = e / C,
                    this.listBoxRegion.controlRect.yPercent = t / R,
                    this.openBackground = this.listBoxRegion.addTextButton("", 0, 0, 1, 1 + i, 1),
                    this.openBackground.setBackground3x3(this.listBoxRegion, 0, 0, a, o, h, l, d, c, u, f, m, p, p),
                    this.closedBackground = this.listBoxRegion.addTextButton("", 0, 0, 1, r, 1),
                    this.closedBackground.setBackground3x1(this.listBoxRegion, 0, 0, g, v, x, y),
                    e = this.labelPixelInset + this.textOffsetsX[0],
                    t = this.labelPixelDrop + this.textOffsetsY[0],
                    t /= this.localPixelsY,
                    e /= this.localPixelsX,
                    this.defaultButton = this.listBoxRegion.addTextButton("Selected", e, -t, 1, r, .5),
                    this.selectedIndex = 0,
                    this.defaultButton.controlRect.linkedControl.innerHTML = this.textEntries[this.selectedIndex],
                    this.defaultButton.linkedBackground = this.closedBackground,
                    this.spacerControl = this.listBoxRegion.addTextButton("", s, k, 1 - (s + A), i, 1),
                    this.spacerControl.defaultAlpha = 1,
                    this.spacerControl.setBackground3x1(this.listBoxRegion, 0, 0, b, S, T, w),
                    this.spacerControl.setVisible(!1),
                    this.spacerControl.linkedBackground = this.openBackground,
                    i = 1; i < n; i++)
                    e = this.labelPixelInset + this.textOffsetsX[i - 1],
                    t = this.labelPixelDrop + this.textOffsetsY[i - 1] - 4,
                    e /= this.localPixelsX,
                    t /= this.localPixelsY,
                    b = this.listBoxRegion.addTextButton(this.textEntries[i - 1], e, r * i - t, 1 - e, r, .5),
                    this.listBoxButtons.push(b),
                    b.linkedBackground = this.openBackground;
                this.showList(!1),
                    this.setupCallbacks()
            },
            y.prototype.setControl = function (e, t, i, s, n, r) {
                var a = this.controlRect.guiScreen.width,
                    o = this.controlRect.guiScreen.height;
                if (n) {
                    n = this.textEntries.length;
                    for (var h = 0; h < n; h++) {
                        var l = 8 * (this.textEntries[h] ? this.textEntries[h].length : 0);
                        i < l && (i = l)
                    }
                    i += r
                }
                this.localPixelsX = i,
                    this.listBoxEntryHeight = s,
                    this.localPixelsY = (this.textEntries.length + 1) * this.listBoxEntryHeight,
                    this.listBoxRegion.controlRect.widthPercent = this.localPixelsX / a,
                    this.listBoxRegion.controlRect.heightPercent = this.localPixelsY / o,
                    this.listBoxRegion.controlRect.xPercent = e / a,
                    this.listBoxRegion.controlRect.yPercent = t / o,
                    this.listBoxRegion.controlRect.updateChildElements(),
                    this.spacerControl.alignBackground(),
                    this.openBackground.alignBackground(),
                    this.closedBackground.alignBackground()
            },
            y.prototype.addItem = function (e, t, i) {
                this.textEntries.push(e),
                    this.textOffsetsX.push(t),
                    this.textOffsetsY.push(i)
            },
            y.prototype.showList = function (e) {
                for (var t = this.listBoxButtons.length, i = 0; i < t; i++)
                    this.listBoxButtons[i].setVisible(e);
                this.closed = !e,
                    this.spacerControl && this.spacerControl.setVisible(e),
                    this.openBackground && this.openBackground.setVisible(e),
                    this.closedBackground && this.closedBackground.setVisible(!e),
                    e ? (this.defaultButton.linkedBackground = this.openBackground,
                        this.openBackground.setOpacity(1),
                        this.closedBackground.setOpacity(.5)) : this.defaultButton.linkedBackground = this.closedBackground
            },
            y.prototype.selectItem = function (e) {
                this.selectedItemText = this.textEntries[e],
                    this.selectedIndex = e,
                    this.defaultButton.controlRect.linkedControl.innerHTML = this.textEntries[this.selectedIndex],
                    e = (this.labelTextHeight - this.listBoxEntryHeight + 3) / this.localPixelsY,
                    this.defaultButton.controlRect.xPercent = (this.labelPixelInset + this.textOffsetsX[this.selectedIndex]) / this.localPixelsX,
                    this.defaultButton.controlRect.yPercent = e,
                    this.defaultButton.controlRect.updateElement()
            },
            y.prototype.setupCallbacks = function () {
                var e = function (e) {
                        if (this.closed) {
                            var t = (t = this.closedBackground.controlRect.linkedControl).getBoundingClientRect(),
                                i = e.clientX - t.left;
                            e = e.clientY - t.top,
                                i /= t.width,
                                t = e / t.height,
                                0 <= i && i <= 1 && 0 <= t && t <= 1 ? this.closedBackground.setOpacity(1) : this.closedBackground.setOpacity(.5)
                        } else
                            t = (t = this.openBackground.controlRect.linkedControl).getBoundingClientRect(),
                            i = e.clientX - t.left,
                            e = e.clientY - t.top,
                            i /= t.width,
                            t = e / t.height,
                            0 <= i && i <= 1 && 0 <= t && t <= 1 ? this.openBackground.setOpacity(1) : this.openBackground.setOpacity(.5)
                    }
                    .bind(this);
                this.defaultButton.controlRect.linkedControl.onclick = function () {
                        this.closed ? this.showList(!0) : (this.showList(this.closed),
                            this.closedBackground.setOpacity(1),
                            this.defaultButton.setOpacity(1))
                    }
                    .bind(this);
                for (var t = function (e) {
                            this.selectItem(e.id),
                                this.showList(!1),
                                this.defaultButton.setOpacity(.5),
                                this.selectionChangedCallback && this.selectionChangedCallback(this)
                        }
                        .bind(this), i = function (e) {
                            e = this.listBoxButtons.length;
                            for (var t = 0; t < e; t++)
                                this.listBoxButtons[t].controlRect.mouseOver && (this.selectItem(t),
                                    t = e,
                                    this.selectionChangedCallback && this.selectionChangedCallback(this));
                            this.showList(!1)
                        }
                        .bind(this), s = this.listBoxButtons.length, n = 0; n < s; n++)
                    this.listBoxButtons[n].controlRect.callBack = t,
                    this.listBoxButtons[n].controlRect.id = n,
                    this.listBoxButtons[n].controlRect.linkedControl.addEventListener("mousemove", e);
                this.guiScreen.ui.viewer.input.element.addEventListener("mousemove", e),
                    this.openBackground.controlRect.linkedControl.addEventListener("mousemove", e),
                    this.closedBackground.controlRect.linkedControl.addEventListener("mousemove", e),
                    this.guiScreen.ui.viewer.input.element.addEventListener("mousedown", i)
            },
            b.prototype.bind = function (e, t) {
                if (!this.complete())
                    return !1;
                var i, s = e.view,
                    n = e.lights,
                    r = e.sky,
                    a = e.shadow,
                    o = e.stripData.active() ? this.stripShader : this.shader,
                    h = this.skinParams,
                    l = this.anisoParams,
                    d = this.microfiberParams,
                    c = this.gl,
                    u = o.params,
                    f = this.textures,
                    m = o.samplers;
                o.bind(),
                    this.blend();
                var p = t.mesh.displayMatrix,
                    g = S.mul(S.empty(), s.viewMatrix, p),
                    v = S.mul(S.empty(), s.projectionMatrix, s.viewMatrix);
                g = S.mul(S.empty(), s.projectionMatrix, g),
                    p = S.mul(S.empty(), n.matrix, p);
                return c.uniformMatrix4fv(u.uModelViewProjectionMatrix, !1, g),
                    c.uniformMatrix4fv(u.uSkyMatrix, !1, p),
                    p = S.mulPoint(V.empty(), n.matrix, s.transform[12], s.transform[13], s.transform[14]),
                    c.uniform3f(u.uCameraPosition, p[0], p[1], p[2]),
                    c.uniform3fv(u.uFresnel, this.fresnel),
                    c.uniform1f(u.uAlphaTest, this.alphaTest),
                    c.uniform1f(u.uHorizonOcclude, this.horizonOcclude),
                    c.uniform1f(u.uHorizonSmoothing, this.horizonSmoothing),
                    c.uniform4fv(u.uDiffuseCoefficients, r.diffuseCoefficients),
                    0 < n.count && (c.uniform4fv(u.uLightPositions, n.positionBuffer),
                        c.uniform3fv(u.uLightDirections, n.directionBuffer),
                        c.uniform3fv(u.uLightColors, n.colors),
                        c.uniform3fv(u.uLightParams, n.parameters),
                        c.uniform3fv(u.uLightSpot, n.spot),
                        p = .392699 * e.postRender.currentSample(),
                        c.uniform2f(u.uShadowKernelRotation, .5 * Math.cos(p), .5 * Math.sin(p)),
                        0 < n.shadowCount && (p = a.depthTextures[0].desc.width,
                            c.uniform2f(u.uShadowMapSize, p, 1 / p),
                            c.uniformMatrix4fv(u.uShadowMatrices, !1, n.finalTransformBuffer),
                            c.uniformMatrix4fv(u.uInvShadowMatrices, !1, n.inverseTransformBuffer),
                            c.uniform4fv(u.uShadowTexelPadProjections, n.shadowTexelPadProjections),
                            a.bindDepthTexture(m.tDepth0, 0),
                            a.bindDepthTexture(m.tDepth1, 1),
                            a.bindDepthTexture(m.tDepth2, 2))),
                    h && (c.uniform3fv(u.uSubdermisColor, h.subdermisColor),
                        c.uniform4fv(u.uTransColor, h.transColor),
                        c.uniform1f(u.uTransScatter, h.transScatter),
                        c.uniform4fv(u.uFresnelColor, h.fresnelColor),
                        c.uniform1f(u.uFresnelOcc, h.fresnelOcc),
                        c.uniform1f(u.uFresnelGlossMask, h.fresnelGlossMask),
                        c.uniform1f(u.uFresnelIntegral, h.fresnelIntegral),
                        c.uniform1f(u.uTransIntegral, h.transIntegral),
                        c.uniform1f(u.uSkinTransDepth, h.transDepth),
                        c.uniform1f(u.uTransSky, h.transSky),
                        c.uniform1f(u.uSkinShadowBlur, h.shadowBlur),
                        c.uniform1f(u.uNormalSmooth, h.normalSmooth),
                        (i = this.extrasTexCoordRanges.subdermisTex) && c.uniform4fv(u.uTexRangeSubdermis, i),
                        (i = this.extrasTexCoordRanges.translucencyTex) && c.uniform4fv(u.uTexRangeTranslucency, i),
                        (i = this.extrasTexCoordRanges.fuzzTex) && c.uniform4fv(u.uTexRangeFuzz, i)),
                    d && (c.uniform4fv(u.uFresnelColor, d.fresnelColor),
                        c.uniform1f(u.uFresnelOcc, d.fresnelOcc),
                        c.uniform1f(u.uFresnelGlossMask, d.fresnelGlossMask),
                        c.uniform1f(u.uFresnelIntegral, d.fresnelIntegral),
                        (i = this.extrasTexCoordRanges.fuzzTex) && c.uniform4fv(u.uTexRangeFuzz, i)),
                    l && (c.uniform3fv(u.uAnisoTangent, l.tangent),
                        c.uniform1f(u.uAnisoStrength, l.strength),
                        c.uniform1f(u.uAnisoIntegral, l.integral),
                        (i = this.extrasTexCoordRanges.anisoTex) && c.uniform4fv(u.uTexRangeAniso, i)),
                    this.usesRefraction && (e.refractionSurface && e.refractionSurface.bind(m.tRefraction),
                        n = S.mul(S.empty(), v, n.invMatrix),
                        c.uniformMatrix4fv(u.uRefractionViewProjection, !1, n),
                        c.uniform1f(u.uRefractionRayDistance, this.refractionParams.distantBackground ? 1e10 : 4 * t.mesh.bounds.maxExtent),
                        c.uniform3fv(u.uRefractionTint, this.refractionParams.tint),
                        c.uniform1f(u.uRefractionAlbedoTint, this.refractionParams.useAlbedoTint ? 1 : 0),
                        c.uniform1f(u.uRefractionIOREntry, 1 / this.refractionParams.IOR),
                        (i = this.extrasTexCoordRanges.refractionMaskTex) && c.uniform4fv(u.uTexRangeRefraction, i)),
                    (i = this.extrasTexCoordRanges.emissiveTex) && (c.uniform4fv(u.uTexRangeEmissive, i),
                        c.uniform1f(u.uEmissiveScale, this.emissiveIntensity)),
                    (i = this.extrasTexCoordRanges.aoTex) && c.uniform4fv(u.uTexRangeAO, i),
                    f.albedo.bind(m.tAlbedo),
                    f.reflectivity.bind(m.tReflectivity),
                    f.normal.bind(m.tNormal),
                    f.extras.bind(m.tExtras),
                    r.specularTexture.bind(m.tSkySpecular),
                    o === this.stripShader && (c.uniform1fv(u.uStrips, e.stripData.strips),
                        c.uniform2f(u.uStripRes, 2 / s.size[0], 2 / s.size[1])),
                    c.uniform2f(u.uUVOffset, this.uOffset, this.vOffset),
                    !0
            },
            b.prototype.bindAlphaPrepass = function (e, t) {
                if (!this.complete() || !this.prepassShader)
                    return !1;
                var i = this.gl,
                    s = this.prepassShader.params,
                    n = this.prepassShader.samplers;
                this.prepassShader.bind();
                var r = S.mul(S.empty(), e.view.viewMatrix, t.mesh.displayMatrix);
                r = S.mul(S.empty(), e.view.projectionMatrix, r);
                return i.uniformMatrix4fv(s.uModelViewProjectionMatrix, !1, r),
                    i.uniform2f(s.uUVOffset, this.uOffset, this.vOffset),
                    this.textures.albedo.bind(n.tAlbedo),
                    !0
            },
            b.prototype.bindWire = function (e, t) {
                if (!this.complete())
                    return !1;
                var i = this.gl,
                    s = this.wireShader.params,
                    n = e.view;
                i.enable(i.BLEND),
                    i.blendFunc(i.SRC_ALPHA, i.ONE_MINUS_SRC_ALPHA),
                    i.depthMask(!1),
                    this.wireShader.bind();
                var r = S.mul(S.empty(), e.view.viewMatrix, t.mesh.displayMatrix);
                r = S.mul(S.empty(), e.view.projectionMatrix, r);
                return i.uniformMatrix4fv(s.uModelViewProjectionMatrix, !1, r),
                    i.uniform4f(s.uStripParams, 2 / n.size[0], 2 / n.size[1], e.stripData.strips[3], e.stripData.strips[4]),
                    !0
            },
            b.prototype.complete = function () {
                return this.wireShader.complete() && this.shader.complete() && this.stripShader.complete() && (!this.prepassShader || this.prepassShader.complete()) && (!this.refractionShader || this.refractionShader.complete()) && this.textures.albedo.complete() && this.textures.reflectivity.complete() && this.textures.normal.complete()
            };
        var S = {
            type: Float32Array,
            create: function (e, t, i, s, n, r, a, o, h, l, d, c, u, f, m, p) {
                var g = new S.type(16);
                return g[0] = e,
                    g[4] = t,
                    g[8] = i,
                    g[12] = s,
                    g[1] = n,
                    g[5] = r,
                    g[9] = a,
                    g[13] = o,
                    g[2] = h,
                    g[6] = l,
                    g[10] = d,
                    g[14] = c,
                    g[3] = u,
                    g[7] = f,
                    g[11] = m,
                    g[15] = p,
                    g
            },
            empty: function () {
                return new S.type(16)
            },
            identity: function () {
                var e = new S.type(16);
                return e[0] = 1,
                    e[4] = 0,
                    e[8] = 0,
                    e[12] = 0,
                    e[1] = 0,
                    e[5] = 1,
                    e[9] = 0,
                    e[13] = 0,
                    e[2] = 0,
                    e[6] = 0,
                    e[10] = 1,
                    e[14] = 0,
                    e[3] = 0,
                    e[7] = 0,
                    e[11] = 0,
                    e[15] = 1,
                    e
            },
            set: function (e, t, i, s, n, r, a, o, h, l, d, c, u, f, m, p, g) {
                e[0] = t,
                    e[4] = i,
                    e[8] = s,
                    e[12] = n,
                    e[1] = r,
                    e[5] = a,
                    e[9] = o,
                    e[13] = h,
                    e[2] = l,
                    e[6] = d,
                    e[10] = c,
                    e[14] = u,
                    e[3] = f,
                    e[7] = m,
                    e[11] = p,
                    e[15] = g
            },
            translation: function (e, t, i, s) {
                return S.set(e, 1, 0, 0, t, 0, 1, 0, i, 0, 0, 1, s, 0, 0, 0, 1),
                    e
            },
            rotation: function (e, t, i) {
                e[0] = 1,
                    e[4] = 0,
                    e[8] = 0,
                    e[12] = 0,
                    e[1] = 0,
                    e[5] = 1,
                    e[9] = 0,
                    e[13] = 0,
                    e[2] = 0,
                    e[6] = 0,
                    e[10] = 1,
                    e[14] = 0,
                    e[3] = 0,
                    e[7] = 0,
                    e[11] = 0,
                    e[15] = 1;
                var s = .0174532925 * t;
                switch (t = Math.sin(s),
                    s = Math.cos(s),
                    i) {
                    case 0:
                        e[5] = s,
                            e[9] = -t,
                            e[6] = t,
                            e[10] = s;
                        break;
                    case 1:
                        e[0] = s,
                            e[8] = t,
                            e[2] = -t,
                            e[10] = s;
                        break;
                    case 2:
                        e[0] = s,
                            e[4] = -t,
                            e[1] = t,
                            e[5] = s
                }
                return e
            },
            mul: function (e, t, i) {
                var s = t[0],
                    n = t[1],
                    r = t[2],
                    a = t[3],
                    o = t[4],
                    h = t[5],
                    l = t[6],
                    d = t[7],
                    c = t[8],
                    u = t[9],
                    f = t[10],
                    m = t[11],
                    p = t[12],
                    g = t[13],
                    v = t[14];
                t = t[15];
                var x = i[0],
                    y = i[1],
                    b = i[2],
                    S = i[3];
                return e[0] = x * s + y * o + b * c + S * p,
                    e[1] = x * n + y * h + b * u + S * g,
                    e[2] = x * r + y * l + b * f + S * v,
                    e[3] = x * a + y * d + b * m + S * t,
                    x = i[4],
                    y = i[5],
                    b = i[6],
                    S = i[7],
                    e[4] = x * s + y * o + b * c + S * p,
                    e[5] = x * n + y * h + b * u + S * g,
                    e[6] = x * r + y * l + b * f + S * v,
                    e[7] = x * a + y * d + b * m + S * t,
                    x = i[8],
                    y = i[9],
                    b = i[10],
                    S = i[11],
                    e[8] = x * s + y * o + b * c + S * p,
                    e[9] = x * n + y * h + b * u + S * g,
                    e[10] = x * r + y * l + b * f + S * v,
                    e[11] = x * a + y * d + b * m + S * t,
                    x = i[12],
                    y = i[13],
                    b = i[14],
                    S = i[15],
                    e[12] = x * s + y * o + b * c + S * p,
                    e[13] = x * n + y * h + b * u + S * g,
                    e[14] = x * r + y * l + b * f + S * v,
                    e[15] = x * a + y * d + b * m + S * t,
                    e
            },
            invert: function (e, t) {
                var i = t[0],
                    s = t[1],
                    n = t[2],
                    r = t[3],
                    a = t[4],
                    o = t[5],
                    h = t[6],
                    l = t[7],
                    d = t[8],
                    c = t[9],
                    u = t[10],
                    f = t[11],
                    m = t[12],
                    p = t[13],
                    g = t[14],
                    v = t[15],
                    x = i * o - s * a,
                    y = i * h - n * a,
                    b = i * l - r * a,
                    S = s * h - n * o,
                    T = s * l - r * o,
                    w = n * l - r * h,
                    C = d * p - c * m,
                    R = d * g - u * m,
                    A = d * v - f * m,
                    k = c * g - u * p,
                    I = c * v - f * p,
                    P = u * v - f * g,
                    F = x * P - y * I + b * k + S * A - T * R + w * C;
                return F ? (F = 1 / F,
                    e[0] = (o * P - h * I + l * k) * F,
                    e[1] = (n * I - s * P - r * k) * F,
                    e[2] = (p * w - g * T + v * S) * F,
                    e[3] = (u * T - c * w - f * S) * F,
                    e[4] = (h * A - a * P - l * R) * F,
                    e[5] = (i * P - n * A + r * R) * F,
                    e[6] = (g * b - m * w - v * y) * F,
                    e[7] = (d * w - u * b + f * y) * F,
                    e[8] = (a * I - o * A + l * C) * F,
                    e[9] = (s * A - i * I - r * C) * F,
                    e[10] = (m * T - p * b + v * x) * F,
                    e[11] = (c * b - d * T - f * x) * F,
                    e[12] = (o * R - a * k - h * C) * F,
                    e[13] = (i * k - s * R + n * C) * F,
                    e[14] = (p * y - m * S - g * x) * F,
                    e[15] = (d * S - c * y + u * x) * F,
                    e) : null
            },
            transpose: function (e, t) {
                return e[0] = t[0],
                    e[4] = t[1],
                    e[8] = t[2],
                    e[12] = t[3],
                    e[1] = t[4],
                    e[5] = t[5],
                    e[9] = t[6],
                    e[13] = t[7],
                    e[2] = t[8],
                    e[6] = t[9],
                    e[10] = t[10],
                    e[14] = t[11],
                    e[3] = t[12],
                    e[7] = t[13],
                    e[11] = t[14],
                    e[15] = t[15],
                    e
            },
            mul4: function (e, t, i, s, n, r) {
                return e[0] = t[0] * i + t[4] * s + t[8] * n + t[12] * r,
                    e[1] = t[1] * i + t[5] * s + t[9] * n + t[13] * r,
                    e[2] = t[2] * i + t[6] * s + t[10] * n + t[14] * r,
                    e[3] = t[3] * i + t[7] * s + t[11] * n + t[15] * r,
                    e
            },
            mulPoint: function (e, t, i, s, n) {
                return e[0] = t[0] * i + t[4] * s + t[8] * n + t[12],
                    e[1] = t[1] * i + t[5] * s + t[9] * n + t[13],
                    e[2] = t[2] * i + t[6] * s + t[10] * n + t[14],
                    e
            },
            mulVec: function (e, t, i, s, n) {
                return e[0] = t[0] * i + t[4] * s + t[8] * n,
                    e[1] = t[1] * i + t[5] * s + t[9] * n,
                    e[2] = t[2] * i + t[6] * s + t[10] * n,
                    e
            },
            perspective: function (e, t, i, s, n, r) {
                return r = r || 0,
                    t = 1 / Math.tan(.00872664625 * t),
                    e[0] = t / i,
                    e[1] = e[2] = e[3] = 0,
                    e[5] = t,
                    e[4] = e[6] = e[7] = 0,
                    e[8] = e[9] = 0,
                    e[10] = (n + s) / (s - n) - 30518044e-12 * r,
                    e[11] = -1,
                    e[14] = 2 * n * s / (s - n),
                    e[12] = e[13] = e[15] = 0,
                    e
            },
            perspectiveInfinite: function (e, t, i, s, n) {
                return n = n || 0,
                    t = 1 / Math.tan(.00872664625 * t),
                    e[0] = t / i,
                    e[1] = e[2] = e[3] = 0,
                    e[5] = t,
                    e[4] = e[6] = e[7] = 0,
                    e[8] = e[9] = 0,
                    e[10] = e[11] = -1 - 30518044e-12 * n,
                    e[14] = -2 * s,
                    e[12] = e[13] = e[15] = 0,
                    e
            },
            ortho: function (e, t, i, s, n, r, a, o) {
                var h = 1 / (i - t),
                    l = 1 / (n - s),
                    d = 1 / (a - r);
                return e[0] = h + h,
                    e[1] = e[2] = e[3] = 0,
                    e[5] = l + l,
                    e[4] = e[6] = e[7] = 0,
                    e[12] = -(i + t) * h,
                    e[13] = -(n + s) * l,
                    e[10] = -(d + d) - 30518044e-12 * (o || 0),
                    e[14] = -(a + r) * d,
                    e[8] = e[9] = e[11] = 0,
                    e[15] = 1,
                    e
            },
            lookAt: function (e, t, i, s) {
                var n = e.subarray(0, 3),
                    r = e.subarray(4, 7),
                    a = e.subarray(8, 11);
                V.sub(a, t, i),
                    V.cross(n, s, a),
                    V.normalize(a, a),
                    V.normalize(n, n),
                    V.cross(r, a, n),
                    S.set(e, n[0], n[1], n[2], -V.dot(n, t), r[0], r[1], r[2], -V.dot(r, t), a[0], a[1], a[2], -V.dot(a, t), 0, 0, 0, 1)
            },
            copy: function (e, t) {
                for (var i = 0; i < 16; ++i)
                    e[i] = t[i]
            },
            copyToBuffer: function (e, t, i) {
                for (var s = 0; s < 16; ++s)
                    e[t + s] = i[s]
            }
        };

        function T(e, t, i) {
            this.gl = e;
            var s = (this.desc = t).isDynamicMesh;
            this.numSubMeshes = this.dynamicVertexData = 0,
                this.displayMatrix = S.identity(),
                this.name = t.name,
                this.modelMatrix = S.identity(),
                this.origin = t.transform ? V.create(t.transform[12], t.transform[13], t.transform[14], 1) : V.create(0, 5, 0, 1),
                this.stride = 32,
                (this.vertexColor = t.vertexColor) && (this.stride += 4),
                (this.secondaryTexCoord = t.secondaryTexCoord) && (this.stride += 8),
                i = new u(i.data),
                this.indexCount = t.indexCount,
                this.indexTypeSize = t.indexTypeSize,
                this.indexType = 4 == this.indexTypeSize ? e.UNSIGNED_INT : e.UNSIGNED_SHORT,
                this.indexBuffer = e.createBuffer(),
                e.bindBuffer(e.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
            var n = i.readBytes(this.indexCount * this.indexTypeSize);
            e.bufferData(e.ELEMENT_ARRAY_BUFFER, n, e.STATIC_DRAW),
                this.wireCount = t.wireCount,
                this.wireBuffer = e.createBuffer(),
                e.bindBuffer(e.ELEMENT_ARRAY_BUFFER, this.wireBuffer),
                n = i.readBytes(this.wireCount * this.indexTypeSize),
                e.bufferData(e.ELEMENT_ARRAY_BUFFER, n, e.STATIC_DRAW),
                e.bindBuffer(e.ELEMENT_ARRAY_BUFFER, null),
                this.vertexCount = t.vertexCount,
                this.vertexBuffer = e.createBuffer(),
                e.bindBuffer(e.ARRAY_BUFFER, this.vertexBuffer),
                i = i.readBytes(this.vertexCount * this.stride),
                s ? (this.dynamicVertexData = new Uint8Array(i),
                    e.bufferData(e.ARRAY_BUFFER, i, e.DYNAMIC_DRAW)) : e.bufferData(e.ARRAY_BUFFER, i, e.STATIC_DRAW),
                e.bindBuffer(e.ARRAY_BUFFER, null),
                this.bounds = void 0 === t.minBound || void 0 === t.maxBound ? {
                    min: V.create(-10, -10, -10, 1),
                    max: V.create(10, 10, -0, 1)
                } : {
                    min: V.create(t.minBound[0], t.minBound[1], t.minBound[2], 1),
                    max: V.create(t.maxBound[0], t.maxBound[1], t.maxBound[2], 1)
                },
                this.bounds.maxExtent = Math.max(Math.max(t.maxBound[0] - t.minBound[0], t.maxBound[1] - t.minBound[1]), t.maxBound[2] - t.minBound[2]),
                this.bounds.averageExtent = (t.maxBound[0] - t.minBound[0] + (t.maxBound[1] - t.minBound[1]) + (t.maxBound[2] - t.minBound[2])) / 3
        }

        function w(e, t, i) {
            this.mesh = e,
                this.gl = this.mesh.gl,
                this.indexOffset = t.firstIndex * e.indexTypeSize,
                this.indexCount = t.indexCount,
                this.wireIndexOffset = t.firstWireIndex * e.indexTypeSize,
                this.wireIndexCount = t.wireIndexCount,
                this.material = i,
                this.visible = !0
        }
        w.prototype.draw = function (e) {
                var t = this.gl;
                if (this.material.bind(e, this)) {
                    e = this.material.shader.attribs;
                    var i = this.mesh.stride;
                    this.mesh.desc.cullBackFaces ? (t.enable(t.CULL_FACE),
                            t.cullFace(t.BACK)) : t.disable(t.CULL_FACE),
                        t.bindBuffer(t.ELEMENT_ARRAY_BUFFER, this.mesh.indexBuffer),
                        t.bindBuffer(t.ARRAY_BUFFER, this.mesh.vertexBuffer),
                        t.enableVertexAttribArray(e.vPosition),
                        t.enableVertexAttribArray(e.vTexCoord),
                        t.enableVertexAttribArray(e.vTangent),
                        t.enableVertexAttribArray(e.vBitangent),
                        t.enableVertexAttribArray(e.vNormal);
                    var s = this.mesh.vertexColor && void 0 !== e.vColor;
                    s && t.enableVertexAttribArray(e.vColor);
                    var n = this.mesh.secondaryTexCoord && void 0 !== e.vTexCoord2;
                    n && t.enableVertexAttribArray(e.vTexCoord2);
                    var r = 0;
                    t.vertexAttribPointer(e.vPosition, 3, t.FLOAT, !1, i, r),
                        r += 12,
                        t.vertexAttribPointer(e.vTexCoord, 2, t.FLOAT, !1, i, r),
                        r += 8,
                        this.mesh.secondaryTexCoord && (n && t.vertexAttribPointer(e.vTexCoord2, 2, t.FLOAT, !1, i, r),
                            r += 8),
                        t.vertexAttribPointer(e.vTangent, 2, t.UNSIGNED_SHORT, !0, i, r),
                        r += 4,
                        t.vertexAttribPointer(e.vBitangent, 2, t.UNSIGNED_SHORT, !0, i, r),
                        r += 4,
                        t.vertexAttribPointer(e.vNormal, 2, t.UNSIGNED_SHORT, !0, i, r),
                        s && t.vertexAttribPointer(e.vColor, 4, t.UNSIGNED_BYTE, !0, i, r + 4),
                        t.drawElements(t.TRIANGLES, this.indexCount, this.mesh.indexType, this.indexOffset),
                        t.disableVertexAttribArray(e.vPosition),
                        t.disableVertexAttribArray(e.vTexCoord),
                        t.disableVertexAttribArray(e.vTangent),
                        t.disableVertexAttribArray(e.vBitangent),
                        t.disableVertexAttribArray(e.vNormal),
                        s && t.disableVertexAttribArray(e.vColor),
                        n && t.disableVertexAttribArray(e.vTexCoord2)
                }
            },
            w.prototype.drawShadow = function (e) {
                var t = this.gl;
                this.mesh.desc.cullBackFaces ? (t.enable(t.CULL_FACE),
                        t.cullFace(t.BACK)) : t.disable(t.CULL_FACE),
                    t.bindBuffer(t.ELEMENT_ARRAY_BUFFER, this.mesh.indexBuffer),
                    t.bindBuffer(t.ARRAY_BUFFER, this.mesh.vertexBuffer),
                    t.enableVertexAttribArray(e),
                    t.vertexAttribPointer(e, 3, t.FLOAT, !1, this.mesh.stride, 0),
                    t.drawElements(t.TRIANGLES, this.indexCount, this.mesh.indexType, this.indexOffset),
                    t.disableVertexAttribArray(e)
            },
            w.prototype.drawAlphaShadow = function (e, t) {
                var i = this.gl;
                this.mesh.desc.cullBackFaces ? (i.enable(i.CULL_FACE),
                        i.cullFace(i.BACK)) : i.disable(i.CULL_FACE),
                    i.bindBuffer(i.ELEMENT_ARRAY_BUFFER, this.mesh.indexBuffer),
                    i.bindBuffer(i.ARRAY_BUFFER, this.mesh.vertexBuffer),
                    i.enableVertexAttribArray(e),
                    i.enableVertexAttribArray(t),
                    i.vertexAttribPointer(e, 3, i.FLOAT, !1, this.mesh.stride, 0),
                    i.vertexAttribPointer(t, 2, i.FLOAT, !1, this.mesh.stride, 12),
                    i.drawElements(i.TRIANGLES, this.indexCount, this.mesh.indexType, this.indexOffset),
                    i.disableVertexAttribArray(e),
                    i.disableVertexAttribArray(t)
            },
            w.prototype.drawAlphaPrepass = function (e) {
                var t = this.gl;
                if (this.material.bindAlphaPrepass(e, this)) {
                    e = this.material.prepassShader.attribs;
                    var i = this.mesh.stride;
                    this.mesh.desc.cullBackFaces ? (t.enable(t.CULL_FACE),
                            t.cullFace(t.BACK)) : t.disable(t.CULL_FACE),
                        t.bindBuffer(t.ELEMENT_ARRAY_BUFFER, this.mesh.indexBuffer),
                        t.bindBuffer(t.ARRAY_BUFFER, this.mesh.vertexBuffer),
                        t.enableVertexAttribArray(e.vPosition),
                        t.enableVertexAttribArray(e.vTexCoord),
                        t.vertexAttribPointer(e.vPosition, 3, t.FLOAT, !1, i, 0),
                        t.vertexAttribPointer(e.vTexCoord, 2, t.FLOAT, !1, i, 12),
                        t.drawElements(t.TRIANGLES, this.indexCount, this.mesh.indexType, this.indexOffset),
                        t.disableVertexAttribArray(e.vPosition),
                        t.disableVertexAttribArray(e.vTexCoord)
                }
            },
            w.prototype.drawWire = function (e) {
                var t = this.material.wireShader.attribs,
                    i = this.gl;
                this.material.bindWire(e, this) && (i.enableVertexAttribArray(t.vPosition),
                    i.bindBuffer(i.ELEMENT_ARRAY_BUFFER, this.mesh.wireBuffer),
                    i.bindBuffer(i.ARRAY_BUFFER, this.mesh.vertexBuffer),
                    i.vertexAttribPointer(t.vPosition, 3, i.FLOAT, !1, this.mesh.stride, 0),
                    i.drawElements(i.LINES, this.wireIndexCount, this.mesh.indexType, this.wireIndexOffset),
                    i.disableVertexAttribArray(t.vPosition))
            },
            w.prototype.complete = function () {
                return this.material.complete()
            };
        var C = {
            fetchImage: function (e, t, i) {
                var s = new Image();
                s.crossOrigin = "Anonymous",
                    s.onload = function () {
                        0 < s.width && 0 < s.height ? t(s) : i && i()
                    },
                    i && (req.onerror = function () {
                        i()
                    }),
                    s.src = e
            },
            fetchText: function (e, t, i, s) {
                var n = new XMLHttpRequest();
                n.open("GET", e, !0),
                    n.onload = function () {
                        200 == n.status ? t(n.responseText) : i && i()
                    },
                    i && (n.onerror = function () {
                        i()
                    }),
                    s && (n.onprogress = function (e) {
                        s(e.loaded, e.total)
                    }),
                    n.send()
            },
            fetchBinary: function (e, t, i, s) {
                var n = new XMLHttpRequest();
                n.open("GET", e, !0),
                    n.responseType = "arraybuffer",
                    n.onload = function () {
                        200 == n.status ? t(n.response) : i && i()
                    },
                    i && (n.onerror = function () {
                        i()
                    }),
                    s && (n.onprogress = function (e) {
                        s(e.loaded, e.total)
                    }),
                    n.send()
            },
            fetchBinaryIncremental: function (r, a, t, o) {
                var i = new XMLHttpRequest();
                i.open("HEAD", r, !0),
                    i.onload = function () {
                        if (200 == i.status) {
                            var e = i.getResponseHeader("Accept-Ranges");
                            if (e && "none" != e) {
                                var s = 0 | i.getResponseHeader("Content-Length"),
                                    n = function (e, t) {
                                        var i = new XMLHttpRequest();
                                        i.open("GET", r, !0),
                                            i.setRequestHeader("Range", "bytes=" + e + "-" + t),
                                            i.responseType = "arraybuffer",
                                            i.onload = function () {
                                                (206 == i.status || 200 == i.status) && a(i.response) && t < s && n(e += o, t = (t += o) < s - 1 ? t : s - 1)
                                            },
                                            i.send()
                                    };
                                n(0, o - 1)
                            } else
                                t && t()
                        } else
                            t && t()
                    },
                    t && (i.onerror = function () {
                        t()
                    }),
                    i.send()
            }
        };

        function R(e) {
            this.debugString = "",
                this.init = !1,
                this.speedList = this.cameraList = this.animationList = this.playButton = this.timelineSlider = this.playbackRegion = this.previousFrameButton = this.nextFrameButton = this.pauseButton = this.playButton = 0,
                this.visible = !1,
                this.backgroundRegion = this.screenButton = 0,
                this.guiScreen = e,
                this.playbackRegion = new v(e),
                this.idealSliderWidth = 650,
                this.totalListBoxPixelsX = 0,
                this.minWidth = 500,
                this.compactMode = !1,
                this.ui = e.ui;
            var t = "animationpause" + e.imageSetNumber + "x.png",
                i = "animationplay" + e.imageSetNumber + "x.png",
                s = "timelineLE" + e.imageSetNumber + "x.png",
                n = "timelineM" + e.imageSetNumber + "x.png",
                r = "timelineRE" + e.imageSetNumber + "x.png",
                a = e.ui.viewer.scene.sceneAnimator.animations.length;
            if (0 != a) {
                var o = this.idealSliderWidth;
                this.bottomOffset = 85,
                    this.centerOffset = 60;
                var h, l = (h = e.width / 2 + this.centerOffset) - o / 2,
                    d = l - 14 - 32,
                    c = (h = h + o / 2) - d,
                    u = 32 / e.height,
                    f = this.bottomOffset / e.height,
                    m = this.playbackRegion;
                if (m.controlRect.widthPercent = c / e.width,
                    m.controlRect.heightPercent = u,
                    m.controlRect.xPercent = d / e.width,
                    m.controlRect.yPercent = f,
                    u = 32 / c,
                    this.pauseButton = new p(this.guiScreen),
                    this.pauseButton.controlRect.set(0, .125, u, .75),
                    this.pauseButton.controlRect.opacity = .5,
                    m.controlRect.registerChildControlRect(this.pauseButton.controlRect),
                    this.pauseButton.linkControl(m.addImageElement(this.pauseButton.controlRect, t)),
                    this.playButton = new p(this.guiScreen),
                    this.playButton.controlRect.set(0, .125, u, .75),
                    this.playButton.controlRect.opacity = .5,
                    m.controlRect.registerChildControlRect(this.playButton.controlRect),
                    this.playButton.linkControl(m.addImageElement(this.playButton.controlRect, i)),
                    t = o / c,
                    c = (l - d) / c,
                    this.timelineSlider = new z(this.guiScreen, m),
                    this.timelineSlider.controlRect.set(c, .03125, t, 1),
                    m.controlRect.registerChildControlRect(this.timelineSlider.controlRect),
                    this.timelineSlider.setBackground3x1(m, s, n, r),
                    this.pauseButton.controlRect.showControl(!e.ui.viewer.scene.sceneAnimator.paused),
                    this.playButton.controlRect.showControl(e.ui.viewer.scene.sceneAnimator.paused),
                    s = h + 14,
                    n = this.bottomOffset + 4,
                    r = e.ui.viewer.scene.sceneAnimator.animations[0].cameraObjects.length,
                    e.ui.viewer.scene.sceneAnimator.selectDefaultCamera(),
                    e.ui.viewer.scene.sceneAnimator.setViewFromSelectedCamera(),
                    this.maxListPixelsX = 0,
                    1 < r) {
                    for (this.cameraList = new y(e),
                        c = 0; c < r; c++)
                        this.cameraList.addItem(e.ui.viewer.scene.sceneAnimator.animations[0].cameraObjects[c].name, 0, 0);
                    this.cameraList.spawnControl(s, n, 10, 24, !0, 8),
                        this.cameraList.selectItem(e.ui.viewer.scene.sceneAnimator.selectedCameraIndex),
                        this.maxListPixelsX = this.cameraList.localPixelsX,
                        this.totalListBoxPixelsX += this.cameraList.localPixelsX + 14
                }
                if (1 < a) {
                    for (this.animationList = new y(e),
                        c = 0; c < a; c++)
                        this.animationList.addItem(e.ui.viewer.scene.sceneAnimator.animations[c].name, 0, 0);
                    this.animationList.spawnControl(s, n, 10, 24, !0, 8),
                        this.maxListPixelsX < this.animationList.localPixelsX && (this.maxListPixelsX = this.animationList.localPixelsX),
                        this.totalListBoxPixelsX += this.animationList.localPixelsX + 14,
                        this.animationList.selectItem(e.ui.viewer.scene.sceneAnimator.selectedAnimationIndex)
                }
                c = h - (s = d - 44 - 14) + this.totalListBoxPixelsX,
                    this.speedList = new y(e),
                    this.speedList.addItem("4.0x", 4, 0),
                    this.speedList.addItem("2.0x", 4, 0),
                    this.speedList.addItem("1.0x", 4, 0),
                    this.speedList.addItem("0.5x", 4, 0),
                    this.speedList.addItem("0.25x", -2, 0),
                    this.speedList.spawnControl(s, n, 44, 24, !1, 0),
                    this.speedList.selectItem(2),
                    c > e.width && (this.idealSliderWidth = e.width - (118 + (this.totalListBoxPixelsX + 14)) - this.centerOffset,
                        e = 0,
                        this.cameraList && e++,
                        this.animationList && e++,
                        1 == e && (this.idealSliderWidth += 56,
                            this.centerOffset -= 14),
                        2 == e && (this.idealSliderWidth += 63,
                            this.centerOffset -= 63)),
                    this.setupCallbacks()
            }
        }

        function A(e, t, i) {
            if (this.gl = e,
                this.desc = t,
                t = [],
                0 != this.desc.sharpen && t.push("#define SHARPEN"),
                (this.useBloom = 0 < this.desc.bloomColor[0] * this.desc.bloomColor[3] || 0 < this.desc.bloomColor[1] * this.desc.bloomColor[3] || 0 < this.desc.bloomColor[2] * this.desc.bloomColor[3]) && t.push("#define BLOOM"),
                0 != this.desc.vignette[3] && t.push("#define VIGNETTE"),
                1 == this.desc.saturation[0] * this.desc.saturation[3] && 1 == this.desc.saturation[1] * this.desc.saturation[3] && 1 == this.desc.saturation[2] * this.desc.saturation[3] || t.push("#define SATURATION"),
                1 == this.desc.contrast[0] * this.desc.contrast[3] && 1 == this.desc.contrast[1] * this.desc.contrast[3] && 1 == this.desc.contrast[2] * this.desc.contrast[3] && 1 == this.desc.brightness[0] * this.desc.brightness[3] && 1 == this.desc.brightness[1] * this.desc.brightness[3] && 1 == this.desc.brightness[2] * this.desc.brightness[3] || t.push("#define CONTRAST"),
                0 != this.desc.grain && t.push("#define GRAIN"),
                1 == this.desc.toneMap ? t.push("#define REINHARD") : 2 == this.desc.toneMap && t.push("#define HEJL"),
                this.desc.colorLUT && t.push("#define COLOR_LUT"),
                this.sampleIndex = 0,
                this.sampleCount = 1,
                i && (this.sampleCount = 4,
                    this.sampleOffsets = [
                        [-.5, -.5],
                        [.5, -.5],
                        [-.5, .5],
                        [.5, .5]
                    ]),
                this.aaShader = e.shaderCache.fromURLs("postvert.glsl", "postaa.glsl"),
                this.shader = e.shaderCache.fromURLs("postvert.glsl", "postfrag.glsl", t),
                this.plainShader = e.shaderCache.fromURLs("postvert.glsl", "postfrag.glsl", []),
                this.fullscreenTriangle = e.createBuffer(),
                e.bindBuffer(e.ARRAY_BUFFER, this.fullscreenTriangle),
                i = new Float32Array([0, 0, 2, 0, 0, 2]),
                e.bufferData(e.ARRAY_BUFFER, i, e.STATIC_DRAW),
                e.bindBuffer(e.ARRAY_BUFFER, null),
                this.useBloom) {
                for (this.bloomTextures = [],
                    this.bloomTargets = [],
                    i = 0; i < 2; ++i)
                    t = {
                        width: 256,
                        height: 256,
                        clamp: !0
                    },
                    this.bloomTextures[i] = new U(e, t),
                    this.bloomTextures[i].loadArray(null, e.RGBA, e.ext.textureHalf && e.ext.textureHalfLinear ? e.ext.textureHalf.HALF_FLOAT_OES : e.UNSIGNED_BYTE),
                    this.bloomTargets[i] = new m(e, {
                        width: t.width,
                        height: t.height,
                        color0: this.bloomTextures[i]
                    });
                for (this.bloomSamples = 64; this.bloomSamples + 16 >= e.limits.fragmentUniforms;)
                    this.bloomSamples /= 2;
                this.bloomShader = e.shaderCache.fromURLs("postvert.glsl", "bloom.glsl", ["#define BLOOM_SAMPLES " + this.bloomSamples]),
                    this.shrinkShader = e.shaderCache.fromURLs("postvert.glsl", "bloomshrink.glsl")
            }
            for (e = new Uint8Array(16384),
                i = 0; i < 16384; i++) {
                t = 255 * Math.random();
                var s = 255 * Math.random();
                e[i] = .5 * (t + s)
            }
            this.noiseTexture = new U(this.gl, {
                    width: 128,
                    height: 128
                }),
                this.noiseTexture.loadArray(e, this.gl.LUMINANCE),
                this.desc.colorLUT && (e = this.desc.colorLUT,
                    this.colorLUT = new U(this.gl, {
                        width: e.length / 3 | 0,
                        height: 1,
                        clamp: !0
                    }),
                    this.colorLUT.loadArray(new Uint8Array(e), this.gl.RGB)),
                this.blackTexture = new U(this.gl, {
                    width: 1,
                    height: 1
                }),
                this.blackTexture.loadArray(new Uint8Array([0, 0, 0, 0])),
                this.bloomResult = this.blackTexture
        }

        function k(e) {
            this.gl = e,
                this.name = "untitled",
                this.meshes = [],
                this.meshRenderables = [],
                this.materials = {},
                this.sky = this.view = null,
                this.selectedPartIndex = 0,
                this.soloPart = !1,
                this.miscnotes = "",
                this.nextView = null,
                this.viewFade = 0,
                this.refractionSurface = this.shadow = this.stripData = this.lights = null,
                this.sceneAnimator = this.frameCounter = 0,
                this.sceneLoaded = !1,
                this.debugString = ""
        }

        function P(e, t, i) {
            if (this.scene = e,
                this.animations = [],
                this.skinningRigs = [],
                this.meshIDs = [],
                this.lightIDs = [],
                this.materialIDs = [],
                this.views = [],
                this.viewYawOffsets = [],
                this.viewPitchOffsets = [],
                this.cameraObjectIndices = [],
                this.cameraChildrenIndices = [],
                this.subMeshObjectIndices = [],
                this.subMeshLiveIndices = [],
                this.scene = e,
                this.selectedCameraIndex = -1,
                this.selectedAnimationIndex = 0,
                this.debugString = "",
                this.scenePlaybackSpeed = this.playbackSpeed = 1,
                this.animationProgress = this.totalSeconds = 0,
                this.paused = this.autoAdvanceNextAnimation = !1,
                this.animateVisibility = this.drawAnimated = this.linkSceneObjects = this.loadSkinningRigs = this.animateMaterials = this.animateTurntables = this.enableSkinning = this.animateMeshes = this.animateLights = this.playAnimations = this.loadAnimations = !0,
                this.showDebugInfo = !1,
                this.loopCount = 0,
                this.loopTurntables = this.lockPlayback = !1,
                this.fogObjectIndex = -1,
                this.unitScaleSkinnedMeshes = !0,
                this.sceneScale = i.sceneScale,
                this.defaultCameraGlobalIndex = i.selectedCamera,
                this.selectedAnimationIndex = i.selectedAnimation,
                this.autoPlayAnims = i.autoPlayAnims,
                this.showPlayControls = i.showPlayControls,
                i.scenePlaybackSpeed && (this.scenePlaybackSpeed = i.scenePlaybackSpeed,
                    0 == this.scenePlaybackSpeed && (this.scenePlaybackSpeed = 1)),
                this.autoPlayAnims || (this.paused = !0),
                this.loadAnimations) {
                if (i.meshIDs)
                    for (var s = i.meshIDs.length, n = 0; n < s; ++n) {
                        var r = i.meshIDs[n].partIndex;
                        this.meshIDs.push(r)
                    }
                if (i.lightIDs)
                    for (s = i.lightIDs.length,
                        n = 0; n < s; ++n)
                        r = (r = i.lightIDs[n]).partIndex,
                        this.lightIDs.push(r);
                if (i.materialIDs)
                    for (s = i.materialIDs.length,
                        n = 0; n < s; ++n)
                        r = (r = i.materialIDs[n]).partIndex,
                        this.materialIDs.push(r);
                if (this.numMatricesInTable = i.numMatrices,
                    r = new u((n = t.get("MatTable.bin")).data),
                    n || (this.numMatricesInTable = 0,
                        this.debugString += "<br>No mattable?"),
                    i.skinningRigs && this.loadSkinningRigs)
                    for (s = i.skinningRigs.length,
                        n = 0; n < s; ++n) {
                        "" == (a = new M(t, i.skinningRigs[n], r)).debugString ? this.skinningRigs.push(a) : (this.debugString += "<br>Error loading skinning rig " + n + " :" + a.debugString,
                            this.debugString += "<br>Skipping the rest",
                            n = s)
                    }
                if (i.animations)
                    for (r = i.animations.length,
                        n = 0; n < r; ++n)
                        s = new c(t, i.animations[n]),
                        this.animations.push(s);
                if (this.startMS = Date.now(),
                    r = this.animations.length,
                    this.linkSceneObjects && 0 != r) {
                    for (n = 0; n < r; n++)
                        for (s = (t = this.animations[n]).animatedObjects.length,
                            i = 0; i < s; i++)
                            "LightSO" == (a = t.animatedObjects[i]).sceneObjectType && (a.lightIndex = this.findLightIndexByPartIndex(i),
                                -1 != a.lightIndex ? t.lightObjects.push(a) : this.debugString += "<br> got light not in scene " + a.name),
                            "FogSO" == a.sceneObjectType && (this.fogObjectIndex = i),
                            "SubMeshSO" == a.sceneObjectType && 0 == n && (this.subMeshObjectIndices.push(i),
                                this.subMeshLiveIndices.push(-1)),
                            "Material" == a.sceneObjectType && (a.materialIndex = this.findMaterialIndexByPartIndex(i),
                                -1 == a.materialIndex ? this.debugString += "<br> can't find material index for object " + i : t.materialObjects.push(a)),
                            "TurnTableSO" == a.sceneObjectType && t.turnTableObjects.push(a),
                            "MeshSO" == a.sceneObjectType && (a.meshIndex = this.findMeshIndexByPartIndex(this.scene.meshes, i),
                                -1 == a.meshIndex ? (this.debugString += "<br> can't find mesh index for object " + i,
                                    this.logObjectInfo(i, 0)) : (t.meshObjects.push(a),
                                    a.mesh = this.scene.meshes[a.meshIndex],
                                    -1 != a.skinningRigIndex && a.mesh && a.skinningRigIndex < this.skinningRigs.length && (a.skinningRig = this.skinningRigs[a.skinningRigIndex],
                                        a.skinningRig.isRigidSkin || (a.mesh.dynamicVertexData ? a.skinningRig.useOriginalMeshVertices(a.mesh) : (this.debugString += "Skinning object - but mesh is not dynamic",
                                            this.debugString += "<br>Rig index " + a.skinningRigIndex,
                                            this.debugString += " not tagged as rigid"))))),
                            "CameraSO" == a.sceneObjectType && (a.modelPartIndex = a.id,
                                t.cameraObjects.push(a));
                    for (i = (t = this.animations[0]).cameraObjects.length,
                        n = 0; n < i; n++)
                        r = t.cameraObjects[n],
                        (s = this.scene.cameras[r.name]) ? (s = s.view) && (s = new H(s),
                            this.cameraObjectIndices.push(r.id),
                            this.views.push(s),
                            this.viewYawOffsets.push(0),
                            this.viewPitchOffsets.push(0)) : (this.debugString += "<br>no camDesc for " + r.name,
                            this.views.push(e.view));
                    for (e = this.scene.meshes.length,
                        r = this.subMeshObjectIndices.length,
                        n = s = 0; n < e; n++) {
                        var a = this.scene.meshes[n],
                            o = !1;
                        for (i = 0; i < r; i++) {
                            var h = this.subMeshObjectIndices[i],
                                l = t.animatedObjects[h],
                                d = t.animatedObjects[l.parentIndex];
                            if (d.mesh || (this.debugString += "<br>submesh parent object has no mesh?",
                                    this.debugString += "<br>obj.name " + l.name,
                                    this.debugString += "<br>parent.name " + d.name,
                                    this.debugString += "<br>submesh index " + i,
                                    this.debugString += "<br>obj.index " + h),
                                d.mesh == a) {
                                for (o = 0; o < a.numSubMeshes; o++)
                                    this.subMeshLiveIndices[i + (a.numSubMeshes - 1 - o)] = s,
                                    s++;
                                i = r,
                                    o = !0
                            }
                        }
                        o || (this.debugString += "<br>Missing submesh? - no matches for mesh " + n + " of " + e)
                    }
                    for (n = 0; n < r; n++)
                        -
                        1 == this.subMeshLiveIndices[n] && (this.debugString += "<br>Missing mesh? Unused submesh " + n + " of " + r);
                    this.showDebugInfo = this.stopEverything = this.runDebugMode = !1,
                        this.selectDefaultCamera(),
                        this.findCameraChildren(),
                        this.findFixedTransforms(),
                        this.runDebugMode && (this.setAnimationProgress(0, !0),
                            "" != this.debugString ? this.stopEverything = !0 : this.checkDebug())
                }
            } else
                this.debugString += "<br>Skip loading animation data"
        }

        function F(e) {
            this.gl = e,
                this.program = null,
                this.params = {},
                this.samplers = {},
                this.attribs = {}
        }

        function O(e) {
            this.gl = e,
                this.cache = []
        }

        function E(e, t) {
            if (this.gl = e,
                this.shadowCount = t,
                this.nativeDepth = !!e.ext.textureDepth,
                this.desc = i,
                i = this.nativeDepth ? ["#define SHADOW_NATIVE_DEPTH"] : [],
                this.shaderSolid = e.shaderCache.fromURLs("shadowvert.glsl", "shadowfrag.glsl", i),
                i.push("#define ALPHA_TEST 1"),
                this.shaderAlphaTest = e.shaderCache.fromURLs("shadowvert.glsl", "shadowfrag.glsl", i),
                this.depthTextures = [],
                this.depthTargets = [],
                0 < this.shadowCount) {
                var i = {
                    width: 2048,
                    height: 2048,
                    clamp: !0,
                    mipmap: !1,
                    nofilter: !0
                };
                e.hints.mobile && (i.width = i.height = 1536);
                var s, n, r = {
                    width: i.width,
                    height: i.height
                };
                n = this.nativeDepth ? (s = e.DEPTH_COMPONENT,
                    e.UNSIGNED_SHORT) : (r.depthBuffer = m.createDepthBuffer(e, i.width, i.height),
                    s = e.RGB,
                    e.UNSIGNED_BYTE);
                for (var a = 0; a < this.shadowCount; ++a)
                    this.depthTextures[a] = new U(e, i),
                    this.depthTextures[a].loadArray(null, s, n),
                    this.nativeDepth ? r.depth = this.depthTextures[a] : r.color0 = this.depthTextures[a],
                    this.depthTargets[a] = new m(e, r)
            }
        }

        function B(e, t, i, s) {
            this.gl = e,
                this.desc = t,
                this.lightCount = s.count,
                this.shadowCount = i.shadowCount,
                (t = this.nativeDepth ? ["#define SHADOW_NATIVE_DEPTH"] : []).push("#define LIGHT_COUNT " + this.lightCount),
                t.push("#define SHADOW_COUNT " + this.shadowCount),
                e.hints.mobile && t.push("#define MOBILE"),
                this.shader = e.shaderCache.fromURLs("shadowfloorvert.glsl", "shadowfloorfrag.glsl", t),
                t = new Float32Array([-1, 0, -1, -1, 0, 1, 1, 0, 1, -1, 0, -1, 1, 0, 1, 1, 0, -1]),
                this.quadGeom = e.createBuffer(),
                e.bindBuffer(e.ARRAY_BUFFER, this.quadGeom),
                e.bufferData(e.ARRAY_BUFFER, t, e.STATIC_DRAW),
                e.bindBuffer(e.ARRAY_BUFFER, null)
        }

        function L() {
            this.associateObjectIndex = this.linkObjectIndex = this.linkMode = 0,
                this.vertexIndices = [],
                this.vertexWeights = [],
                this.matrix = S.identity(),
                this.defaultAssociateWorldTransform = this.defaultClusterWorldTransform = this.defaultClusterBaseTransform = 0,
                this.defaultClusterWorldTransformInvert = S.identity(),
                this.defaultAssociateWorldTransformInvert = S.identity(),
                this.debugString = ""
        }

        function M(e, t, i) {
            if (this.debugString = "",
                this.skinningClusters = [],
                this.srcVFile = t.file,
                e = e.get(this.srcVFile))
                if (e.data) {
                    this.rigByteStream = new u(e.data),
                        e = new Uint32Array(this.rigByteStream.bytes.buffer, 0, this.rigByteStream.bytes.length / 4),
                        this.expectedNumClusters = e[0],
                        this.expectedNumVertices = e[1],
                        this.numClusterLinks = e[2],
                        this.originalObjectIndex = e[3],
                        this.isRigidSkin = e[4],
                        this.tangentMethod = e[5],
                        t = 6 + 7 * this.expectedNumClusters;
                    for (var s = 0; s < this.expectedNumClusters; s++) {
                        var n = new L();
                        this.skinningClusters.push(n);
                        var r = 6 + 7 * s;
                        n.linkMode = e[1 + r],
                            n.linkObjectIndex = e[2 + r],
                            n.associateObjectIndex = e[3 + r];
                        var a = e[5 + r];
                        n.defaultClusterWorldTransform = i.getMatrix(e[4 + r]),
                            n.defaultClusterBaseTransform = i.getMatrix(a),
                            S.invert(n.defaultClusterWorldTransformInvert, n.defaultClusterWorldTransform),
                            1 == n.linkMode && (n.defaultAssociateWorldTransform = i.getMatrix(e[6 + r]),
                                S.invert(n.defaultAssociateWorldTransformInvert, n.defaultAssociateWorldTransform))
                    }
                    e = (t = (i = 4 * t) + this.expectedNumVertices) + 2 * this.numClusterLinks,
                        t = new Uint8Array(this.rigByteStream.bytes.subarray(t)),
                        e = new Uint8Array(this.rigByteStream.bytes.subarray(e)),
                        this.linkMapCount = new Uint8Array(this.rigByteStream.bytes.buffer, i, this.expectedNumVertices),
                        this.linkMapClusterIndices = new Uint16Array(t.buffer),
                        this.linkMapWeights = new Float32Array(e.buffer)
                } else
                    this.debugString += "<br>No data in " + this.srcVFile;
            else
                this.debugString += "<br>Error loading buffer for skinning rig " + this.srcVFile
        }

        function _(e, t, i) {
            if (this.gl = e,
                void 0 !== (s = t.extract("sky.dat") || t.extract("sky.png"))) {
                this.specularTexture = new U(e, {
                        width: 256,
                        height: 2048,
                        clamp: !0
                    }),
                    t = s.data;
                for (var s, n = (s = s.data.length) / 4, r = new Uint8Array(s), a = 0, o = 0; a < s; ++o)
                    r[a++] = t[o + 2 * n],
                    r[a++] = t[o + n],
                    r[a++] = t[o],
                    r[a++] = t[o + 3 * n];
                this.specularTexture.loadArray(r)
            }
            if (this.diffuseCoefficients = new Float32Array(i.diffuseCoefficients),
                this.backgroundMode = i.backgroundMode || 0,
                this.backgroundBrightness = i.backgroundBrightness || 1,
                this.backgroundColor = new Float32Array(i.backgroundColor),
                1 <= this.backgroundMode)
                if (this.backgroundShader = e.shaderCache.fromURLs("skyvert.glsl", 3 == this.backgroundMode ? "skySH.glsl" : "sky.glsl", ["#define SKYMODE " + this.backgroundMode]),
                    this.vertexBuffer = e.createBuffer(),
                    e.bindBuffer(e.ARRAY_BUFFER, this.vertexBuffer),
                    i = 1 / 256,
                    s = 2.8 * (t = .5 / 256),
                    n = .5 * t,
                    i = new Float32Array([0, 1, 0, .49609375 + i, .49609375 + i, 1, 0, 0, .9921875 + i, .49609375 + i, 0, 0, 1, .49609375 + i, .9921875 + i, -1, 0, 0, 0 + i, .49609375 + i, 0, 0, -1, .49609375 + i, 0 + i, 0, -1, 0, .9921875 + i, 0 + i, 0, -1, 0, .9921875 + i, .9921875 + i, 0, -1, 0, 0 + i, .9921875 + i, 0, -1, 0, 0 + i, 0 + i, s, 1 - s, -s, .5 + t, .5 - t, s, 1 - s, s, .5 + t, .5 + t, -s, 1 - s, s, .5 - t, .5 + t, -s, 1 - s, -s, .5 - t, .5 - t, -s, 0, -1 + s, .5 - t, 0 + i + t, s, 0, -1 + s, .5 + t, 0 + i + t, 1 - s, 0, -s, .9921875 + i - t, .5 - t, 1 - s, 0, s, .9921875 + i - t, .5 + t, s, 0, 1 - s, .5 + t, .9921875 + i - t, -s, 0, 1 - s, .5 - t, .9921875 + i - t, -1 + s, 0, s, 0 + i + t, .5 + t, -1 + s, 0, -s, 0 + i + t, .5 - t, 1, 0, 0, .9921875 + i - n, .49609375 + i, 0, 0, 1, .49609375 + i, .9921875 + i - n, -1, 0, 0, 0 + i + n, .49609375 + i, 0, 0, -1, .49609375 + i, 0 + i + n, 0, 1, 0, .49609375 + i - n, .49609375 + i, 0, 1, 0, .49609375 + i, .49609375 + i - n, 0, 1, 0, .49609375 + i + n, .49609375 + i, 0, 1, 0, .49609375 + i, .49609375 + i + n]),
                    e.bufferData(e.ARRAY_BUFFER, i, e.STATIC_DRAW),
                    e.bindBuffer(e.ARRAY_BUFFER, null),
                    this.indexBuffer = e.createBuffer(),
                    e.bindBuffer(e.ELEMENT_ARRAY_BUFFER, this.indexBuffer),
                    i = new Uint16Array([2, 1, 6, 3, 2, 7, 8, 4, 3, 4, 5, 1, 9, 14, 15, 17, 10, 16, 18, 19, 11, 20, 13, 12, 28, 12, 13, 13, 24, 28, 28, 24, 9, 9, 24, 14, 25, 9, 15, 25, 15, 21, 10, 25, 21, 10, 21, 16, 22, 26, 10, 22, 10, 17, 18, 11, 26, 22, 18, 26, 19, 23, 27, 19, 27, 11, 23, 20, 27, 27, 20, 12]),
                    this.skyIndexCount = i.length,
                    e.bufferData(e.ELEMENT_ARRAY_BUFFER, i, e.STATIC_DRAW),
                    e.bindBuffer(e.ELEMENT_ARRAY_BUFFER, null),
                    3 == this.backgroundMode)
                    for (this.backgroundCoefficients = new Float32Array(this.diffuseCoefficients),
                        a = 0; a < this.backgroundCoefficients.length; ++a)
                        this.backgroundCoefficients[a] *= this.backgroundBrightness;
                else {
                    var h;
                    this.backgroundTexture = new U(e, {
                            width: 256,
                            height: 256,
                            clamp: !0
                        }),
                        i = !1,
                        e.ext.textureHalf && e.ext.textureHalfLinear && (this.backgroundTexture.loadArray(null, e.RGB, e.ext.textureHalf.HALF_FLOAT_OES),
                            i = (h = new m(e, {
                                color0: this.backgroundTexture
                            })).valid),
                        !i && e.ext.textureFloat && e.ext.textureFloatLinear && !e.hints.mobile && (this.backgroundTexture.loadArray(null, e.RGB, e.FLOAT),
                            i = (h = new m(e, {
                                color0: this.backgroundTexture
                            })).valid),
                        i || (this.backgroundTexture.loadArray(),
                            h = new m(e, {
                                color0: this.backgroundTexture
                            })),
                        h.bind(),
                        (h = new F(e)).build("precision highp float; varying vec2 tc; attribute vec4 p; void main(){ gl_Position=p; tc=vec2(0.5,0.5/8.0)*p.xy+vec2(0.5,6.5/8.0); }", "precision highp float; varying vec2 tc; uniform sampler2D tex; uniform float b; void main(){vec4 s=texture2D(tex,tc); gl_FragColor.xyz=s.xyz*(b*s.w);}"),
                        h.bind(),
                        e.uniform1f(h.params.b, 7 * Math.sqrt(this.backgroundBrightness)),
                        this.specularTexture.bind(h.samplers.tex),
                        i = e.createBuffer(),
                        e.bindBuffer(e.ARRAY_BUFFER, i),
                        i = new Float32Array([-1, -1, .5, 1, 3, -1, .5, 1, -1, 3, .5, 1]),
                        e.bufferData(e.ARRAY_BUFFER, i, e.STATIC_DRAW),
                        e.enableVertexAttribArray(h.attribs.p),
                        e.vertexAttribPointer(h.attribs.p, 4, e.FLOAT, !1, 0, 0),
                        e.drawArrays(e.TRIANGLES, 0, 3),
                        e.disableVertexAttribArray(h.attribs.p)
                }
        }

        function D() {
            this.STRIP_NONE = -2,
                this.STRIP_MENU = -1,
                this.stripCount = 5,
                this.strips = [0, 0, 0, 0, 0],
                this.labels = ["Normals", "Albedo", "Reflectivity", "Gloss", "Topology"],
                this.stripSlant = .25,
                this.selectedStrip = this.STRIP_NONE,
                this.animationActive = !1,
                this.timestamp = Date.now(),
                this.update(!0)
        }

        function U(e, t) {
            this.gl = e,
                this.id = null,
                this.type = e.TEXTURE_2D,
                this.format = e.RGBA,
                this.componentType = e.UNSIGNED_BYTE,
                t = t || {},
                this.desc = {
                    width: t.width || 1,
                    height: t.height || 1,
                    mipmap: t.mipmap,
                    clamp: t.clamp,
                    mirror: t.mirror,
                    aniso: t.aniso,
                    nofilter: t.nofilter
                }
        }

        function N(e) {
            this.gl = e,
                this.cache = []
        }

        function z(e, t) {
            this.name = "none",
                this.debugString = "",
                this.knobControlRect = new s(e),
                this.controlRect = new s(e);
            var i = document.createElement("div");
            i.id = "sliderUI",
                i.style.position = "absolute",
                i.style.overflow = "hidden",
                i.style["-moz-user-select"] = "none",
                i.style["-khtml-user-select"] = "none",
                i.style["-webkit-user-select"] = "none",
                i.style["-ms-user-select"] = "none",
                this.controlRect.linkedControl = i,
                this.backgroundControl = 0,
                this.controlRect.registerChildControlRect(this.knobControlRect),
                this.knobControlRect.setOpacity(.65),
                this.sliderPercent = this.pixelsY = this.pixelsX = 0,
                this.draggingSlider = !1,
                this.guiScreen = e,
                t.addImageElement(this.knobControlRect, "animationknob" + e.imageSetNumber + "x.png")
        }

        function j(e) {
            this.viewer = e,
                this.stripData = e.stripData,
                (e = this.container = document.createElement("div")).id = "fdageUI",
                e.style.position = "absolute",
                e.style.overflow = "hidden",
                e.style["-moz-user-select"] = "none",
                e.style["-khtml-user-select"] = "none",
                e.style["-webkit-user-select"] = "none",
                e.style["-ms-user-select"] = "none",
                this.viewer.domRoot.appendChild(e),
                this.guiScreen = new t(this)
        }
        R.prototype.resize = function (e) {
                e.ui.viewer.scene.sceneAnimator.showPlayControls || (e.width = 1,
                        e.height = 1),
                    this.compactMode = e.width < this.minWidth;
                var t = this.bottomOffset,
                    i = this.bottomOffset + 4,
                    s = 0;
                this.cameraList && this.animationList ? s += 42 + this.cameraList.localPixelsX + this.animationList.localPixelsX : this.cameraList ? s += 28 + this.cameraList.localPixelsX : this.animationList && (s += 28 + this.animationList.localPixelsX);
                var n = e.width - s - 72;
                0 == s && (n -= 14);
                var r = 116,
                    a = r + n + 14;
                this.compactMode && (r = 58,
                    n += 44 + s,
                    0 < s && (t += 32),
                    s || (i += 32));
                var o = (s = 32 / n) + 14 / n,
                    h = 1 - o,
                    l = this.playbackRegion;
                l.controlRect.widthPercent = n / e.width,
                    l.controlRect.heightPercent = 32 / e.height,
                    l.controlRect.xPercent = r / e.width,
                    l.controlRect.yPercent = t / e.height,
                    this.pauseButton.controlRect.set(0, .125, s, .75),
                    this.playButton.controlRect.set(0, .125, s, .75),
                    this.timelineSlider.controlRect.set(o, .03125, h, 1),
                    this.timelineSlider.setSize(n - 46, 32),
                    l.controlRect.updateElement(),
                    l.controlRect.updateChildElements(),
                    this.speedList.setControl(58, i, 44, 24, !1),
                    this.cameraList && (this.cameraList.setControl(a, i, 10, 24, !0, 8),
                        a += this.cameraList.localPixelsX + 14),
                    this.animationList && this.animationList.setControl(a, i, 10, 24, !0, 8),
                    this.timelineSlider.backgroundControl.alignBackground()
            },
            R.prototype.setupCallbacks = function () {
                var e = function (e) {
                        "0.01x" == this.speedList.selectedItemText && this.ui.viewer.scene.sceneAnimator.setPlaybackSpeed(.01),
                            "0.05x" == this.speedList.selectedItemText && this.ui.viewer.scene.sceneAnimator.setPlaybackSpeed(.05),
                            "0.25x" == this.speedList.selectedItemText && this.ui.viewer.scene.sceneAnimator.setPlaybackSpeed(.25),
                            "0.5x" == this.speedList.selectedItemText && this.ui.viewer.scene.sceneAnimator.setPlaybackSpeed(.5),
                            "1.0x" == this.speedList.selectedItemText && this.ui.viewer.scene.sceneAnimator.setPlaybackSpeed(1),
                            "2.0x" == this.speedList.selectedItemText && this.ui.viewer.scene.sceneAnimator.setPlaybackSpeed(2),
                            "4.0x" == this.speedList.selectedItemText && this.ui.viewer.scene.sceneAnimator.setPlaybackSpeed(4)
                    }
                    .bind(this),
                    t = function (e) {
                        this.ui.viewer.scene.sceneAnimator.selectCamera(this.cameraList.selectedIndex),
                            this.ui.viewer.wake()
                    }
                    .bind(this),
                    i = function (e) {
                        this.ui.viewer.scene.sceneAnimator.selectAnimation(this.animationList.selectedIndex),
                            this.ui.viewer.wake()
                    }
                    .bind(this);
                this.speedList && (this.speedList.selectionChangedCallback = e),
                    this.cameraList && (this.cameraList.selectionChangedCallback = t),
                    this.animationList && (this.animationList.selectionChangedCallback = i),
                    this.playButton.controlRect.linkedControl.onclick = function () {
                        this.ui.viewer.scene.sceneAnimator.pause(!1),
                            this.playButton.controlRect.showControl(!1),
                            this.pauseButton.controlRect.showControl(!0),
                            this.ui.viewer.wake()
                    }
                    .bind(this),
                    this.pauseButton.controlRect.linkedControl.onclick = function () {
                        this.ui.viewer.scene.sceneAnimator.pause(!0),
                            this.playButton.controlRect.showControl(!0),
                            this.pauseButton.controlRect.showControl(!1)
                    }
                    .bind(this)
            },
            A.prototype.prepareBloom = function (e) {
                if (this.useBloom && this.bloomShader.complete() && this.shrinkShader.complete()) {
                    this.shrinkShader.bind(),
                        this.bloomTargets[1].bind(),
                        e.bind(this.shrinkShader.samplers.tInput),
                        this.fillScreen(this.shrinkShader.attribs.vCoord),
                        this.bloomShader.bind();
                    var t = [];
                    this.bloomTargets[0].bind(),
                        this.bloomTextures[1].bind(this.bloomShader.samplers.tInput);
                    for (var i = 0, s = 0; s < this.bloomSamples; ++s) {
                        var n, r = 2 * s / (this.bloomSamples - 1) - 1;
                        n = 4 * r,
                            i += n = Math.exp(-.5 * n * n / 1) / 2.50662827463,
                            t[4 * s + 0] = r * this.desc.bloomSize,
                            t[4 * s + 1] = 0,
                            t[4 * s + 2] = n,
                            t[4 * s + 3] = 0
                    }
                    for (s = 0; s < this.bloomSamples; ++s)
                        t[4 * s + 2] /= i;
                    for (this.gl.uniform4fv(this.bloomShader.params.uKernel, t),
                        this.fillScreen(this.bloomShader.attribs.vCoord),
                        this.bloomTargets[1].bind(),
                        this.bloomTextures[0].bind(this.bloomShader.samplers.tInput),
                        s = 0; s < this.bloomSamples; ++s)
                        i = t[4 * s + 0],
                        i *= e.desc.width / e.desc.height,
                        t[4 * s + 0] = 0,
                        t[4 * s + 1] = i;
                    this.gl.uniform4fv(this.bloomShader.params.uKernel, t),
                        this.fillScreen(this.bloomShader.attribs.vCoord),
                        this.bloomResult = this.bloomTextures[1]
                } else
                    this.bloomResult = this.blackTexture
            },
            A.prototype.computeParams = function (e, t) {
                var i = this.desc,
                    s = {};
                s.scale = [i.contrast[0] * i.contrast[3], i.contrast[1] * i.contrast[3], i.contrast[2] * i.contrast[3]],
                    s.bias = [i.bias[0] * i.bias[3], i.bias[1] * i.bias[3], i.bias[2] * i.bias[3]],
                    s.bias = [-s.bias[0] * s.scale[0] + s.bias[0], -s.bias[1] * s.scale[1] + s.bias[1], -s.bias[2] * s.scale[2] + s.bias[2]];
                var n = [i.brightness[0] * i.brightness[3], i.brightness[1] * i.brightness[3], i.brightness[2] * i.brightness[3]];
                s.scale = [s.scale[0] * n[0], s.scale[1] * n[1], s.scale[2] * n[2]],
                    s.bias = [s.bias[0] * n[0], s.bias[1] * n[1], s.bias[2] * n[2]],
                    s.saturation = [i.saturation[0] * i.saturation[3], i.saturation[1] * i.saturation[3], i.saturation[2] * i.saturation[3]],
                    s.bloomColor = [i.bloomColor[0] * i.bloomColor[3], i.bloomColor[1] * i.bloomColor[3], i.bloomColor[2] * i.bloomColor[3]],
                    s.sharpen = [i.sharpen, .25 * i.sharpen, i.sharpenLimit],
                    s.sharpenKernel = [1 / e, 0, 0, 1 / t],
                    n = t < e ? e : t,
                    s.vignetteAspect = [e / n, t / n, .5 * e / n, .5 * t / n],
                    s.vignette = [2 * (1 - i.vignette[0]) * i.vignette[3], 2 * (1 - i.vignette[1]) * i.vignette[3], 2 * (1 - i.vignette[2]) * i.vignette[3], i.vignetteCurve];
                n = 1 / this.noiseTexture.desc.width;
                var r = 1 / this.noiseTexture.desc.height,
                    a = 1 - i.grainSharpness;
                return s.grainCoord = [n * e, r * t, .5 * a * n, .5 * a * r],
                    s.grainScaleBias = [2 * i.grain, -i.grain],
                    s
            },
            A.prototype.present = function (e, t, i, s) {
                if (s || this.prepareBloom(e),
                    1 < this.sampleCount && this.allocAABuffer(t, i),
                    (s = s ? this.plainShader : this.shader).bind()) {
                    var n = this.gl,
                        r = s.samplers,
                        a = s.params,
                        o = this.computeParams(t, i);
                    if (e.bind(r.tInput),
                        this.bloomResult.bind(r.tBloom),
                        this.noiseTexture.bind(r.tGrain),
                        this.colorLUT && this.colorLUT.bind(r.tLUT),
                        n.uniform3fv(a.uScale, o.scale),
                        n.uniform3fv(a.uBias, o.bias),
                        n.uniform3fv(a.uSaturation, o.saturation),
                        n.uniform4fv(a.uSharpenKernel, o.sharpenKernel),
                        n.uniform3fv(a.uSharpness, o.sharpen),
                        n.uniform3fv(a.uBloomColor, o.bloomColor),
                        n.uniform4fv(a.uVignetteAspect, o.vignetteAspect),
                        n.uniform4fv(a.uVignette, o.vignette),
                        n.uniform4fv(a.uGrainCoord, o.grainCoord),
                        n.uniform2fv(a.uGrainScaleBias, o.grainScaleBias),
                        e = 1 < this.sampleCount && 0 <= this.sampleIndex) {
                        var h = 1 / (1 + this.sampleIndex);
                        this.sampleIndex += 1,
                            h < 1 && (n.enable(n.BLEND),
                                n.blendColor(h, h, h, h),
                                n.blendFunc(n.CONSTANT_ALPHA, n.ONE_MINUS_CONSTANT_ALPHA)),
                            this.aaTarget.bind()
                    } else
                        m.bindNone(n),
                        1 < this.sampleCount && (this.sampleIndex += 1);
                    n.viewport(0, 0, t, i),
                        this.fillScreen(s.attribs.vCoord),
                        e && (h < 1 && n.disable(n.BLEND),
                            m.bindNone(n),
                            this.aaShader.bind(),
                            this.aaBuffer.bind(this.aaShader.samplers.tInput),
                            this.fillScreen(this.aaShader.attribs.vCoord))
                }
            },
            A.prototype.allocAABuffer = function (e, t) {
                this.aaBuffer && this.aaBuffer.desc.width == e && this.aaBuffer.desc.height == t || (this.aaBuffer && this.aaBuffer.destroy(),
                    this.aaBuffer = new U(this.gl, {
                        width: e,
                        height: t,
                        clamp: !0
                    }),
                    this.aaBuffer.loadArray(),
                    this.aaTarget = new m(this.gl, {
                        color0: this.aaBuffer,
                        ignoreStatus: !0
                    }))
            },
            A.prototype.adjustProjectionForSupersampling = function (e) {
                if (1 < this.sampleCount) {
                    var t = this.currentSample(),
                        i = this.sampleOffsets[t][0] / e.size[0];
                    t = this.sampleOffsets[t][1] / e.size[1],
                        i = S.translation(S.empty(), i, t, 0);
                    S.mul(e.projectionMatrix, i, e.projectionMatrix)
                }
            },
            A.prototype.discardAAHistory = function () {
                this.sampleIndex = -1
            },
            A.prototype.currentSample = function () {
                return (this.sampleIndex < 0 ? 0 : this.sampleIndex) % this.sampleCount
            },
            A.prototype.fillScreen = function (e) {
                var t = this.gl;
                t.bindBuffer(t.ARRAY_BUFFER, this.fullscreenTriangle),
                    t.enableVertexAttribArray(e),
                    t.vertexAttribPointer(e, 2, t.FLOAT, !1, 0, 0),
                    t.drawArrays(t.TRIANGLES, 0, 3),
                    t.disableVertexAttribArray(e),
                    t.bindBuffer(t.ARRAY_BUFFER, null)
            },
            A.prototype.blitTexture = function (e) {
                this.aaShader.bind(),
                    e.bind(this.aaShader.samplers.tInput),
                    this.fillScreen(this.aaShader.attribs.vCoord)
            },
            k.prototype.load = function (e) {
                var t, i = this.gl,
                    s = e.extract("scene.json");
                if (void 0 === s)
                    return !1;
                if (!e.checkSignature(s))
                    return !1;
                if (null == (s = new u(s.data).asString()) || s.length <= 0)
                    return !1;
                try {
                    t = JSON.parse(s)
                } catch (e) {
                    return console.error(e),
                        !1
                }
                for (var n in this.metaData = t.metaData,
                        this.view = new H(t.mainCamera.view),
                        this.sky = new _(this.gl, e, t.sky),
                        this.lights = new x(t.lights, this.view),
                        this.materialsList = [],
                        this.materials = {},
                        t.materials) {
                    var r = t.materials[n];
                    r.lightCount = this.lights.count,
                        r.shadowCount = this.lights.shadowCount,
                        s = new b(this.gl, e, r),
                        this.materials[r.name] = s,
                        this.materialsList.push(s)
                }
                if (t.meshes)
                    for (r = 0; r < t.meshes.length; ++r) {
                        n = t.meshes[r],
                            n = new T(this.gl, n, e.extract(n.file)),
                            this.meshes.push(n);
                        for (var a = 0; a < n.desc.subMeshes.length; ++a) {
                            var o = n.desc.subMeshes[a];
                            (s = this.materials[o.material]) && (n.numSubMeshes++,
                                this.meshRenderables.push(new w(n, o, s)))
                        }
                    }
                return this.bounds = new d(this.meshes),
                    this.postRender = new A(this.gl, t.mainCamera.post, !0),
                    this.shadow = new E(i, this.lights.shadowCount),
                    this.cameras = t.Cameras,
                    t.AnimData && (this.sceneAnimator = new P(this, e, t.AnimData)),
                    t.fog && (this.fog = new f(i, t.fog)),
                    t.shadowFloor && (this.shadowFloor = new B(i, t.shadowFloor, this.shadow, this.lights)),
                    this.sceneLoaded = !0
            },
            k.prototype.update = function () {
                this.sceneAnimator && (this.frameCounter++,
                        this.lights.flagUpdateAnimatedLighting(),
                        this.sceneAnimator.drawAnimated && (1 == this.frameCounter ? this.sceneAnimator.resetPlayback() : this.sceneAnimator.updateAnimationPlayback())),
                    this.lights.update(this.view, this.bounds)
            },
            k.prototype.collectShadows = function (e) {
                this.shadow.collect(this, e)
            },
            k.prototype.draw = function (e) {
                var t = this.gl;
                if (this.sceneLoaded) {
                    this.sky.setClearColor(),
                        t.clear(t.COLOR_BUFFER_BIT | t.DEPTH_BUFFER_BIT | t.STENCIL_BUFFER_BIT),
                        t.enable(t.DEPTH_TEST),
                        this.sky.draw(this),
                        this.shadowFloor && this.shadowFloor.draw(this);
                    for (var i = 0; i < this.meshRenderables.length; ++i)
                        this.meshRenderables[i].material.usesBlending || this.meshRenderables[i].material.usesRefraction || !this.meshRenderables[i].visible || this.meshRenderables[i].draw(this);
                    for (t.enable(t.POLYGON_OFFSET_FILL),
                        t.polygonOffset(1, 1),
                        t.colorMask(!1, !1, !1, !1),
                        i = 0; i < this.meshRenderables.length; ++i)
                        this.meshRenderables[i].drawAlphaPrepass(this);
                    for (t.colorMask(!0, !0, !0, !0),
                        t.disable(t.POLYGON_OFFSET_FILL),
                        t.depthFunc(t.LEQUAL),
                        t.depthMask(!1),
                        i = 0; i < this.meshRenderables.length; ++i)
                        this.meshRenderables[i].material.usesBlending && this.meshRenderables[i].visible && this.meshRenderables[i].draw(this);
                    t.disable(t.BLEND),
                        t.depthMask(!0),
                        t.depthFunc(t.LESS);
                    var s = !1;
                    for (i = 0; i < this.meshRenderables.length; ++i)
                        if (this.meshRenderables[i].material.usesRefraction) {
                            s = !0;
                            break
                        }
                    if (s)
                        for (this.refractionSurface && this.refractionSurface.desc.width == e.color0.desc.width && this.refractionSurface.desc.height == e.color0.desc.height || (this.refractionSurface = new U(t, e.color0.desc),
                                this.refractionSurface.loadArray(null, e.color0.format, e.color0.componentType),
                                this.refractionBuffer = new m(this.gl, {
                                    color0: this.refractionSurface
                                })),
                            this.refractionBuffer.bind(),
                            this.postRender.blitTexture(e.color0),
                            e.bind(),
                            i = 0; i < this.meshRenderables.length; ++i)
                            this.meshRenderables[i].material.usesRefraction && this.meshRenderables[i].visible && this.meshRenderables[i].draw(this);
                    if (this.stripData.activeWireframe() && 0 < this.meshRenderables.length) {
                        for (i = 0; i < this.meshRenderables.length; ++i)
                            this.meshRenderables[i].visible && this.meshRenderables[i].drawWire(this);
                        t.depthMask(!0)
                    }
                    t.disable(t.BLEND)
                }
            },
            k.prototype.drawSecondary = function (e) {
                this.fog && this.fog.draw(this, e)
            },
            k.prototype.complete = function () {
                if (!this.sky.complete() || !this.shadow.complete() || this.fog && !this.fog.complete() || this.shadowFloor && !this.shadowFloor.complete())
                    return !1;
                for (var e = 0; e < this.meshRenderables.length; ++e)
                    if (!this.meshRenderables[e].complete())
                        return !1;
                return !0
            },
            P.prototype.flagAllForDebugging = function () {
                for (var e = this.animations.length, t = 0; t < e; t++)
                    for (var i = this.animations[t], s = i.animatedObjects.length, n = 0; n < s; n++)
                        i.animatedObjects[n].debugMe = !0
            },
            P.prototype.checkDebug = function () {
                this.debugString = "<br>--------------------------------------Debug Info:",
                    this.debugString += "<br>this.selectedAnimationIndex :" + this.selectedAnimationIndex;
                var e = this.animations[this.selectedAnimationIndex],
                    t = e.animatedObjects.length;
                this.debugString += "<br>numAnimatedObjects :" + t,
                    "" != e.debugString && (this.debugString += "<br>--------------------------------------------------Got animation bug info:",
                        this.debugString += e.debugString,
                        this.showDebugInfo = this.stopEverything = !0,
                        e.debugString = "");
                for (var i = 0; i < t; i++) {
                    var s = e.animatedObjects[i];
                    "" == s.debugString && "" == s.animatedLocalTransform.debugString || (this.debugString += "<br>--------------------------------------------------Got object bug info:",
                            this.debugString += s.debugString,
                            this.debugString += s.animatedLocalTransform.debugString,
                            this.showDebugInfo = this.stopEverything = !0,
                            s.debugString = "",
                            s.animatedLocalTransform.debugString = ""),
                        s.skinningRig && "" != s.skinningRig.debugString && (this.debugString += "<br>--------------------------------------------------Got skin rig info:",
                            this.debugString += s.skinningRig.debugString,
                            s.skinningRig.debugString = "",
                            this.showDebugInfo = this.stopEverything = !0)
                }
                this.debugString += "<br>--------------------------------------Done Debug Info:"
            },
            P.prototype.logObjectInfo = function (e, t) {
                var i = t * (o = this.animations[this.selectedAnimationIndex]).originalFPS;
                if (e >= o.animatedObjects.length)
                    this.debugString += "object index " + e + " exceeds " + o.animatedObjects.length;
                else {
                    var s = o.animatedObjects[e],
                        n = o.animatedObjects[s.modelPartIndex],
                        r = o.getObjectAnimationFramePercent(s, t),
                        a = o.getObjectAnimationFramePercent(n, t);
                    this.debugString = "",
                        this.debugString += "<br>Object Name: " + s.name,
                        this.debugString += "<br>Object Type: " + s.sceneObjectType,
                        this.debugString += "<br>Object Index: " + s.id,
                        this.debugString += "<br>Part Index: " + s.modelPartIndex,
                        this.debugString += "<br>Part Scale: " + s.modelPartScale,
                        this.debugString += "<br>Mesh Index: " + s.meshIndex,
                        this.debugString += "<br>Light Index: " + s.lightIndex,
                        this.debugString += "<br>Deformer Index: " + s.skinningRigIndex,
                        this.debugString += "<br>Parent Index: " + s.parentIndex,
                        this.debugString += "<br>Scene time " + t,
                        this.debugString += "<br>Scene framepercent " + i,
                        this.debugString += "<br>Object looped framepercent " + r,
                        this.debugString += "<br>Model  looped framepercent " + a,
                        this.debugString += "<br>Object Anim length " + s.animationLength,
                        this.debugString += "<br>Object Total frames " + s.totalFrames,
                        this.debugString += "<br>Object FPS " + s.modelPartFPS,
                        this.debugString += "<br>Model Part Anim length " + n.animationLength,
                        this.debugString += "<br>Model total frames " + n.totalFrames,
                        this.debugString += "<br>Model Part FPS " + n.modelPartFPS,
                        i = S.identity(),
                        o.getWorldTransform(s.id, t, i, this.sceneScale, !0),
                        this.debugString += s.debugString;
                    var o = i[0],
                        h = (s = i[1],
                            n = i[2],
                            r = i[4],
                            a = i[5],
                            i[6]),
                        l = i[8],
                        d = i[9];
                    i = i[10];
                    Math.sqrt(o * o + s * s + n * n),
                        Math.sqrt(r * r + a * a + h * h),
                        Math.sqrt(l * l + d * d + i * i)
                }
            },
            P.prototype.resetPlayback = function () {
                this.startMS = Date.now(),
                    this.animationProgress = this.totalSeconds = 0,
                    this.setAnimationProgress(0, !0)
            },
            P.prototype.pause = function (e) {
                this.paused = e,
                    this.startMS = Date.now() - 1e3 * this.totalSeconds / (this.playbackSpeed * this.scenePlaybackSpeed)
            },
            P.prototype.setAnimationProgress = function (e, t) {
                var i = this.animations[this.selectedAnimationIndex];
                this.animationProgress = e,
                    this.totalSeconds = i.totalSeconds * this.animationProgress,
                    this.totalSeconds -= 1 / i.originalFPS,
                    this.totalSeconds < 0 && (this.totalSeconds = 0),
                    this.startMS = Date.now() - 1e3 * this.totalSeconds / (this.playbackSpeed * this.scenePlaybackSpeed),
                    t && this.updateScene()
            },
            P.prototype.setPlaybackSpeed = function (e) {
                this.playbackSpeed = e,
                    this.startMS = Date.now() - 1e3 * this.totalSeconds / (this.playbackSpeed * this.scenePlaybackSpeed)
            },
            P.prototype.resetCustomView = function () {
                0 <= this.selectedCameraIndex && this.selectedCameraIndex < this.views.length && (this.viewYawOffsets[this.selectedCameraIndex] = 0,
                    this.viewPitchOffsets[this.selectedCameraIndex] = 0,
                    this.scene.view.rotation[1] = this.views[this.selectedCameraIndex].rotation[1],
                    this.scene.view.rotation[0] = this.views[this.selectedCameraIndex].rotation[0],
                    this.setViewFromSelectedCamera())
            },
            P.prototype.updateUserCamera = function () {
                if (this.clearCacheForCameraChildren(),
                    0 <= this.selectedCameraIndex && this.selectedCameraIndex < this.views.length && this.selectedAnimationIndex < this.animations.length) {
                    var e = this.cameraObjectIndices[this.selectedCameraIndex],
                        t = this.animations[this.selectedAnimationIndex];
                    if (e < t.animatedObjects.length) {
                        var i = this.views[this.selectedCameraIndex],
                            s = this.scene.view.rotation[1],
                            n = this.scene.view.rotation[0],
                            r = n - i.rotation[0];
                        this.viewYawOffsets[this.selectedCameraIndex] = s - i.rotation[1],
                            this.viewPitchOffsets[this.selectedCameraIndex] = r,
                            i = t.animatedObjects[e],
                            t.getObjectAnimationFramePercent(i, this.totalSeconds);
                        r = S.identity();
                        var a = S.identity();
                        i.useFixedWorldTransform = !1,
                            i.useFixedLocalTransform = !1,
                            i.animatedLocalTransform.lockTransform = !1,
                            i.animatedLocalTransform.clearCachedTransforms(),
                            i.cachedFrame0 = -1,
                            i.cachedFrame1 = -1,
                            i.cachedFrame2 = -1,
                            i.cachedFrame3 = -1,
                            i.cachedFrameUse0 = 0,
                            i.cachedFrameUse1 = 0,
                            i.cachedFrameUse2 = 0,
                            i.cachedFrameUse3 = 0,
                            t.getWorldTransform(e, this.totalSeconds, a, this.sceneScale, !1);
                        e = a[0];
                        var o = a[1],
                            h = a[2],
                            l = a[4],
                            d = a[5],
                            c = a[6],
                            u = a[8],
                            f = a[9],
                            m = a[10];
                        e = Math.sqrt(e * e + o * o + h * h),
                            l = Math.sqrt(l * l + d * d + c * c),
                            d = Math.sqrt(u * u + f * f + m * m);
                        (c = -(this.scene.view.pivot[0] - a[12])) * u + (o = -(this.scene.view.pivot[1] - a[13])) * f + (a = -(this.scene.view.pivot[2] - a[14])) * m <= 0 && (s += 180),
                            s = S.rotation(S.empty(), s, 1),
                            n = S.rotation(S.empty(), n, 0),
                            S.mul(r, s, n),
                            n = Math.sqrt(c * c + o * o + a * a),
                            s = this.scene.view.pivot[1] + r[9] * n,
                            a = this.scene.view.pivot[2] + r[10] * n,
                            r[12] = this.scene.view.pivot[0] + r[8] * n,
                            r[13] = s,
                            r[14] = a,
                            n = S.identity(),
                            t.getWorldTransform(i.parentIndex, this.totalSeconds, n, this.sceneScale, !1),
                            t = S.identity(),
                            S.invert(t, n),
                            n = S.identity(),
                            S.mul(n, t, r),
                            n[12] /= this.sceneScale,
                            n[13] /= this.sceneScale,
                            n[14] /= this.sceneScale,
                            r[0] *= e,
                            r[1] *= e,
                            r[2] *= e,
                            r[4] *= l,
                            r[5] *= l,
                            r[6] *= l,
                            r[8] *= d,
                            r[9] *= d,
                            r[10] *= d,
                            i.setFixedWorldTransform(r),
                            i.setFixedLocalTransform(n)
                    }
                }
            },
            P.prototype.setViewFromSelectedCamera = function () {
                if (0 <= this.selectedCameraIndex && this.selectedCameraIndex < this.views.length) {
                    var e = this.views[this.selectedCameraIndex],
                        t = this.scene.view,
                        i = this.viewYawOffsets[this.selectedCameraIndex],
                        s = this.viewPitchOffsets[this.selectedCameraIndex];
                    t.pivot[0] = e.pivot[0],
                        t.pivot[1] = e.pivot[1],
                        t.pivot[2] = e.pivot[2],
                        t.rotation[0] = e.rotation[0] + s,
                        t.rotation[1] = e.rotation[1] + i,
                        t.radius = e.radius,
                        t.nearPlane = e.nearPlane,
                        t.fov = e.fov,
                        t.saveResetView(),
                        t.updateProjection(),
                        t.updateView()
                }
            },
            P.prototype.selectDefaultCamera = function () {
                if (-1 != this.defaultCameraGlobalIndex && 0 < this.animations.length)
                    for (var e = this.animations[0], t = e.cameraObjects.length, i = 0; i < t; i++)
                        if (e.cameraObjects[i].id == this.defaultCameraGlobalIndex)
                            return void(this.selectedCameraIndex = i);
                this.selectedCameraIndex = 0
            },
            P.prototype.updateAnimationPlayback = function () {
                if (!this.stopEverything || !this.runDebugMode) {
                    var e = this.animations[this.selectedAnimationIndex];
                    if (this.updateUserCamera(),
                        this.paused || !this.playAnimations)
                        this.startMS = 0 < this.playbackSpeed ? Date.now() - 1e3 * this.totalSeconds / (this.playbackSpeed * this.scenePlaybackSpeed) : Date.now() - 1e3 * this.totalSeconds,
                        this.refreshTransformsOnly(),
                        this.runDebugMode && this.checkDebug(),
                        (e = this.scene.view).saveResetView(),
                        e.updateProjection(),
                        e.updateView();
                    else {
                        this.lockPlayback && 0 < this.playbackSpeed && (this.startMS = Date.now() - 1e3 * this.totalSeconds / (this.playbackSpeed * this.scenePlaybackSpeed));
                        var t = (Date.now() - this.startMS) / 1e3 * this.playbackSpeed * this.scenePlaybackSpeed;
                        this.totalSeconds = (Date.now() - this.startMS) / 1e3 * this.playbackSpeed * this.scenePlaybackSpeed;
                        var i = (i = t / e.totalSeconds) - (t = Math.floor(i));
                        t != this.loopCount && (this.loopCount++,
                                this.loopTurntables && this.rolloverTurntables(),
                                this.autoAdvanceNextAnimation && (this.nextAnimation(),
                                    this.resetPlayback())),
                            this.totalSeconds = e.totalSeconds * i,
                            this.animationProgress = this.totalSeconds / e.totalSeconds - Math.floor(this.totalSeconds / e.totalSeconds),
                            this.updateScene(),
                            this.runDebugMode && this.checkDebug()
                    }
                }
            },
            P.prototype.updateScene = function () {
                this.lastSceneFramePercent = this.totalSeconds * this.animations[this.selectedAnimationIndex].originalFPS,
                    0 != this.fogObjectIndex && this.updateFog(),
                    this.animateTurntables && this.updateTurntables(),
                    this.animateMeshes && this.poseMeshes(),
                    this.animateLights && this.updateLights(),
                    this.animateMaterials && this.updateMaterials(),
                    this.animateVisibility && this.updateVisibility()
            },
            P.prototype.findCameraChildren = function () {
                for (var e = this.animations[0], t = e.animatedObjects.length, i = 0; i < t; i++)
                    e.hasParentTypeInHierarchy(e.animatedObjects[i], "CameraSO") && this.cameraChildrenIndices.push(i)
            },
            P.prototype.findFixedTransforms = function () {
                for (var e = this.animations.length, t = 0; t < e; t++)
                    for (var i = this.animations[t], s = i.animatedObjects.length, n = 0; n < s; n++) {
                        var r = i.animatedObjects[n];
                        if (!r.useFixedWorldTransform && !i.hasAnimationInHierarchy(r))
                            if ("Material" == r.sceneObjectType)
                                r.setFixedWorldTransform(S.identity()),
                                r.setFixedLocalTransform(S.identity());
                            else {
                                var a = S.identity(),
                                    o = S.identity();
                                i.hasParentTypeInHierarchy(r, "SceneRootSO") ? (i.getWorldTransform(r.id, 0, a, this.sceneScale, !1),
                                        r.evaluateLocalTransformAtFramePercent(0, o, !0, !1)) : (i.evaluateModelPartTransformAtFrame(r.id, 0, a, !1),
                                        r.evaluateLocalTransformAtFramePercent(0, o, !1, !1)),
                                    r.setFixedWorldTransform(a),
                                    r.setFixedLocalTransform(o)
                            }
                    }
            },
            P.prototype.clearCacheForCameraChildren = function () {
                for (var e = this.animations[this.selectedAnimationIndex], t = this.cameraChildrenIndices.length, i = 0; i < t; i++) {
                    var s = e.animatedObjects[this.cameraChildrenIndices[i]];
                    s.useFixedWorldTransform = !1,
                        s.useFixedLocalTransform = !1,
                        s.cachedFrame0 = -10,
                        s.cachedFrame1 = -10,
                        s.cachedFrame2 = -10,
                        s.cachedFrame3 = -10,
                        s.cachedFrameUse0 = 0,
                        s.cachedFrameUse1 = 0,
                        s.cachedFrameUse2 = 0,
                        s.cachedFrameUse3 = 0,
                        s.animatedLocalTransform.clearCachedTransforms(),
                        s.animatedLocalTransform.lockTransform = !1
                }
            },
            P.prototype.refreshTransformsOnly = function () {
                for (var e = this.animations[this.selectedAnimationIndex], t = e.meshObjects.length, i = 0; i < t; i++) {
                    var s = e.meshObjects[i];
                    if (e.getWorldTransform(s.id, this.totalSeconds, s.mesh.displayMatrix, this.sceneScale, !0),
                        this.enableSkinning && s.skinningRig && this.unitScaleSkinnedMeshes && !s.skinningRig.isRigidSkin) {
                        var n = (s = s.mesh.displayMatrix)[0],
                            r = s[1],
                            a = s[2],
                            o = s[4],
                            h = s[5],
                            l = s[6],
                            d = s[8],
                            c = s[9],
                            u = s[10];
                        d = ((n = Math.sqrt(n * n + r * r + a * a)) + (o = Math.sqrt(o * o + h * h + l * l)) + (d = Math.sqrt(d * d + c * c + u * u))) / 2;
                        s[0] /= d,
                            s[1] /= d,
                            s[2] /= d,
                            s[4] /= d,
                            s[5] /= d,
                            s[6] /= d,
                            s[8] /= d,
                            s[9] /= d,
                            s[10] /= d
                    }
                }
                if (this.animateLights)
                    for (t = e.lightObjects.length,
                        i = 0; i < t; i++)
                        (s = e.lightObjects[i]).useFixedWorldTransform || (d = this.scene.lights.getLightPos(s.lightIndex),
                            c = this.scene.lights.getLightDir(s.lightIndex),
                            u = S.identity(),
                            e.getWorldTransform(s.id, this.totalSeconds, u, this.sceneScale, !0),
                            c[0] = u[8],
                            c[1] = u[9],
                            c[2] = u[10],
                            0 != d[3] && (d[0] = u[12],
                                d[1] = u[13],
                                d[2] = u[14],
                                this.scene.lights.setLightPos(s.lightIndex, d)),
                            this.scene.lights.setLightDir(s.lightIndex, c))
            },
            P.prototype.findMeshIndexByPartIndex = function (e, t) {
                for (var i = 0; i < this.meshIDs.length; ++i)
                    if (t == this.meshIDs[i])
                        return i;
                return -1
            },
            P.prototype.findLightIndexByPartIndex = function (e) {
                for (var t = 0; t < this.lightIDs.length; t++)
                    if (e == this.lightIDs[t])
                        return t;
                return -1
            },
            P.prototype.findMaterialIndexByPartIndex = function (e) {
                for (var t = 0; t < this.materialIDs.length; t++)
                    if (e == this.materialIDs[t])
                        return t;
                return -1
            },
            P.prototype.nextAnimation = function () {
                this.selectedAnimationIndex++,
                    this.selectedAnimationIndex >= this.animations.length && (this.selectedAnimationIndex = 0)
            },
            P.prototype.selectAnimation = function (e) {
                0 <= e && e < this.animations.length && (this.selectedAnimationIndex = e),
                    this.paused && this.setAnimationProgress(this.animationProgress, !0)
            },
            P.prototype.selectCamera = function (e) {
                -1 != e && this.selectedCameraIndex != e && (this.selectedCameraIndex = e,
                    this.setViewFromSelectedCamera())
            },
            P.prototype.getAnimatedCamera = function () {
                if (0 <= this.selectedCameraIndex && this.selectedAnimationIndex < this.animations.length) {
                    var e = this.animations[this.selectedAnimationIndex];
                    if (this.selectedCameraIndex < e.cameraObjects.length)
                        return e.cameraObjects[this.selectedCameraIndex]
                }
            },
            P.prototype.poseMeshes = function () {
                for (var e = this.animations[this.selectedAnimationIndex], t = e.meshObjects.length, i = 0; i < t; i++) {
                    var s = e.meshObjects[i];
                    if (this.enableSkinning && s.skinningRig)
                        if (s.skinningRig.isRigidSkin)
                            e.getWorldTransform(s.id, this.totalSeconds, s.mesh.displayMatrix, this.sceneScale, !0);
                        else {
                            s.setupSkinningRig(e, s.modelPartIndex, this.totalSeconds, s.skinningRig),
                                e.getWorldTransform(s.id, this.totalSeconds, s.mesh.displayMatrix, this.sceneScale, !0);
                            var n = s.modelPartScale * this.sceneScale;
                            if (this.unitScaleSkinnedMeshes) {
                                var r = s.mesh.displayMatrix,
                                    a = r[0],
                                    o = r[1],
                                    h = r[2],
                                    l = r[4],
                                    d = r[5],
                                    c = r[6],
                                    u = r[8],
                                    f = r[9],
                                    m = r[10];
                                u = ((a = Math.sqrt(a * a + o * o + h * h)) + (l = Math.sqrt(l * l + d * d + c * c)) + (u = Math.sqrt(u * u + f * f + m * m))) / 2;
                                r[0] /= u,
                                    r[1] /= u,
                                    r[2] /= u,
                                    r[4] /= u,
                                    r[5] /= u,
                                    r[6] /= u,
                                    r[8] /= u,
                                    r[9] /= u,
                                    r[10] /= u,
                                    n *= u
                            }
                            s.skinningRig.deformMesh(s.mesh, n)
                        }
                    else
                        e.getWorldTransform(s.id, this.totalSeconds, s.mesh.displayMatrix, this.sceneScale, !0)
                }
            },
            P.prototype.updateLights = function () {
                for (var e = this.animations[this.selectedAnimationIndex], t = this.totalSeconds * e.originalFPS, i = e.lightObjects.length, s = 0; s < i; s++) {
                    var n = e.lightObjects[s],
                        r = this.scene.lights.getLightPos(n.lightIndex),
                        a = this.scene.lights.getLightDir(n.lightIndex),
                        o = this.scene.lights.getLightColor(n.lightIndex),
                        h = S.identity(),
                        l = 1;
                    n.useFixedWorldTransform || e.getWorldTransform(n.id, this.totalSeconds, h, this.sceneScale, !0),
                        n.redProperty && (n.redProperty.evaluate(t, o[0], n),
                            o[0] = n.redProperty.lastValue),
                        n.greenProperty && (n.greenProperty.evaluate(t, o[1], n),
                            o[1] = n.greenProperty.lastValue),
                        n.blueProperty && (n.blueProperty.evaluate(t, o[2], n),
                            o[2] = n.blueProperty.lastValue),
                        n.brightnessProperty && (n.brightnessProperty.evaluate(t, l, n),
                            l = n.brightnessProperty.lastValue),
                        o[0] *= l,
                        o[1] *= l,
                        o[2] *= l,
                        0 != r[3] && (n.useFixedWorldTransform || (r[0] = h[12],
                                r[1] = h[13],
                                r[2] = h[14],
                                this.scene.lights.setLightPos(n.lightIndex, r)),
                            n.spotAngleProperty && 0 < this.scene.lights.spot[3 * n.lightIndex] && (r = 0,
                                n.spotAngleProperty.evaluate(t, r, n),
                                r = n.spotAngleProperty.lastValue,
                                this.scene.lights.setLightSpotAngle(n.lightIndex, r)),
                            n.spotSharpnessProperty && (r = 0,
                                n.spotSharpnessProperty.evaluate(t, r, n),
                                r = n.spotSharpnessProperty.lastValue,
                                this.scene.lights.setLightSpotSharpness(n.lightIndex, r)),
                            n.distanceProperty && (r = 1,
                                n.distanceProperty.evaluate(t, r, n),
                                r = n.distanceProperty.lastValue * this.sceneScale,
                                this.scene.lights.setLightDistance(n.lightIndex, r))),
                        n.useFixedWorldTransform || (a[0] = h[8],
                            a[1] = h[9],
                            a[2] = h[10],
                            this.scene.lights.setLightDir(n.lightIndex, a)),
                        this.scene.lights.setLightColor(n.lightIndex, o)
                }
            },
            P.prototype.updateTurntables = function () {
                for (var e = this.animations[this.selectedAnimationIndex], t = this.totalSeconds * e.originalFPS, i = e.turnTableObjects.length, s = 0; s < i; s++) {
                    var n = e.turnTableObjects[s];
                    n.spinProperty.evaluate(t, 0, n),
                        n.turnTableSpin = n.turnTableSpinOffset + n.spinProperty.lastValue * this.totalSeconds
                }
            },
            P.prototype.rolloverTurntables = function () {
                for (var e = this.animations[this.selectedAnimationIndex], t = e.turnTableObjects.length, i = 0; i < t; i++) {
                    var s = e.turnTableObjects[i];
                    s.turnTableSpinOffset = s.turnTableSpin
                }
            },
            P.prototype.updateMaterials = function () {
                for (var e = this.animations[this.selectedAnimationIndex], t = this.totalSeconds * e.originalFPS, i = e.materialObjects.length, s = 0; s < i; s++) {
                    var n = e.materialObjects[s];
                    n.offsetUProperty && (n.offsetUProperty.evaluate(t, 0, n),
                            this.scene.materialsList[n.materialIndex].uOffset = n.offsetUProperty.lastValue),
                        n.offsetVProperty && (n.offsetVProperty.evaluate(t, 0, n),
                            this.scene.materialsList[n.materialIndex].vOffset = n.offsetVProperty.lastValue),
                        n.emissiveProperty && 1 < n.emissiveProperty.numKeyframes && (n.emissiveProperty.evaluate(t, 0, n),
                            this.scene.materialsList[n.materialIndex].emissiveIntensity = n.emissiveProperty.lastValue)
                }
            },
            P.prototype.updateFog = function () {
                var e = this.animations[this.selectedAnimationIndex],
                    t = this.totalSeconds * e.originalFPS;
                0 <= this.fogObjectIndex && this.fogObjectIndex < e.animatedObjects.length && this.scene.fog && ((e = e.animatedObjects[this.fogObjectIndex]).redProperty && (this.scene.fog.desc.color[0] = e.redProperty.evaluate(t, this.scene.fog.desc.color[0], e)),
                    e.greenProperty && (this.scene.fog.desc.color[1] = e.greenProperty.evaluate(t, this.scene.fog.desc.color[1], e)),
                    e.blueProperty && (this.scene.fog.desc.color[2] = e.blueProperty.evaluate(t, this.scene.fog.desc.color[2], e)),
                    e.distanceProperty && (this.scene.fog.desc.distance = e.distanceProperty.evaluate(t, this.scene.fog.desc.distance, e)),
                    e.opacityProperty && (this.scene.fog.desc.opacity = e.opacityProperty.evaluate(t, this.scene.fog.desc.opacity, e)),
                    e.skyIllumProperty && (this.scene.fog.desc.skyIllum = e.skyIllumProperty.evaluate(t, this.scene.fog.desc.skyIllum, e)),
                    e.lightIllumProperty && (this.scene.fog.desc.lightIllum = e.lightIllumProperty.evaluate(t, this.scene.fog.desc.lightIllum, e)),
                    e.dispersionProperty && (this.scene.fog.desc.dispersion = e.dispersionProperty.evaluate(t, this.scene.fog.desc.dispersion, e)))
            },
            P.prototype.updateVisibility = function () {
                for (var e = this.animations[this.selectedAnimationIndex], t = this.subMeshObjectIndices.length, i = 0; i < t; i++) {
                    if (-1 != (n = this.subMeshLiveIndices[i])) {
                        var s = this.subMeshObjectIndices[i],
                            n = this.scene.meshRenderables[n],
                            r = e.getObjectAnimationFramePercent(e.animatedObjects[s], this.totalSeconds);
                        n.visible = e.isVisibleAtFramePercent(s, r)
                    }
                }
            },
            F.prototype.build = function (e, t) {
                var i = this.gl;
                this.program = i.createProgram(),
                    this.params = {},
                    this.samplers = {},
                    this.attribs = {};
                var s = function (e) {
                        for (var t = "", i = e.indexOf("\n"), s = 0; - 1 != i;)
                            t += ++s + ": ",
                            t += e.substring(0, i + 1),
                            i = (e = e.substring(i + 1, e.length)).indexOf("\n");
                        console.log(t)
                    },
                    n = i.createShader(i.VERTEX_SHADER);
                i.shaderSource(n, e),
                    i.compileShader(n),
                    i.getShaderParameter(n, i.COMPILE_STATUS) || (console.log(i.getShaderInfoLog(n)),
                        I.verboseErrors && s(e)),
                    i.attachShader(this.program, n),
                    n = i.createShader(i.FRAGMENT_SHADER),
                    i.shaderSource(n, t),
                    i.compileShader(n),
                    i.getShaderParameter(n, i.COMPILE_STATUS) || (console.log(i.getShaderInfoLog(n)),
                        I.verboseErrors && s(t)),
                    i.attachShader(this.program, n),
                    i.linkProgram(this.program),
                    i.getProgramParameter(this.program, i.LINK_STATUS) || console.log(i.getProgramInfoLog(this.program));
                n = i.getProgramParameter(this.program, i.ACTIVE_UNIFORMS);
                var r = 0;
                for (s = 0; s < n; ++s) {
                    var a = i.getActiveUniform(this.program, s),
                        o = a.name,
                        h = o.indexOf("[");
                    0 <= h && (o = o.substring(0, h)),
                        h = i.getUniformLocation(this.program, a.name),
                        a.type == i.SAMPLER_2D || a.type == i.SAMPLER_CUBE ? this.samplers[o] = {
                            location: h,
                            unit: r++
                        } : this.params[o] = h
                }
                for (n = i.getProgramParameter(this.program, i.ACTIVE_ATTRIBUTES),
                    s = 0; s < n; ++s)
                    r = i.getActiveAttrib(this.program, s),
                    this.attribs[r.name] = i.getAttribLocation(this.program, r.name)
            },
            F.prototype.bind = function () {
                return !!this.program && (this.gl.useProgram(this.program),
                    !0)
            },
            F.prototype.complete = function () {
                return !!this.program
            },
            O.prototype.fromURLs = function (e, t, i) {
                var s = "";
                if (i)
                    for (var n = 0; n < i.length; ++n)
                        s = i[n] + "\n" + s;
                if (i = s + ":" + e + "|" + t,
                    void 0 !== (n = this.cache[i]))
                    return n;

                function r() {
                    null != o && null != h && a.build(o, h)
                }
                var a = new F(this.gl),
                    o = null,
                    h = null;
                return this.fetch(e, function (e) {
                        o = s + e,
                            r()
                    }),
                    this.fetch(t, function (e) {
                        h = s + e,
                            r()
                    }),
                    this.cache[i] = a
            },
            O.prototype.fetch = function (e, t) {
                void 0 !== G ? void 0 !== G[e] ? this.resolveIncludes(new String(G[e]), t) : t("") : C.fetchText("src/shader/" + e, function (e) {
                        this.resolveIncludes(e, t)
                    }
                    .bind(this),
                    function () {
                        t("")
                    })
            },
            O.prototype.resolveIncludes = function (t, i) {
                for (var r = [], a = !0, e = function (e, t, i, s, n) {
                        return a = !0,
                            r.push({
                                offset: n,
                                path: t.slice(1, t.length - 1)
                            }),
                            ""
                    }; a;)
                    a = !1,
                    t = t.replace(/#include\s((<[^>]+>)|("[^"]+"))/, e);
                if (0 < r.length) {
                    var s = r.length;
                    for (e = 0; e < r.length; ++e)
                        this.fetch(r[e].path, function (e) {
                                if (this.src = e,
                                    --s <= 0) {
                                    for (e = r.length - 1; 0 <= e; --e)
                                        t = t.substring(0, r[e].offset) + r[e].src + t.substring(r[e].offset);
                                    i(t)
                                }
                            }
                            .bind(r[e]))
                } else
                    i(t)
            },
            E.prototype.bindDepthTexture = function (e, t) {
                this.shadowCount > t && this.depthTextures[t].bind(e)
            },
            E.prototype.collect = function (e, t) {
                for (var i = this.gl, s = e.lights, n = s.shadowCount, r = s.modelViewBuffer, a = s.projectionBuffer, o = s.matrix, h = 0 != e.sceneAnimator, l = S.empty(), d = !1, c = 0; c < n; ++c)
                    if (s.shadowsNeedUpdate[c]) {
                        d = !(s.shadowsNeedUpdate[c] = 0),
                            S.mul(l, r.subarray(16 * c, 16 * (c + 1)), o),
                            S.mul(l, a.subarray(16 * c, 16 * (c + 1)), l),
                            this.depthTargets[c].bind(),
                            i.clearColor(1, 1, 1, 1),
                            i.clear(i.COLOR_BUFFER_BIT | i.DEPTH_BUFFER_BIT);
                        var u = this.shaderSolid;
                        u.bind(),
                            i.uniformMatrix4fv(u.params.uViewProjection, !1, l),
                            i.uniformMatrix4fv(u.params.uMeshTransform, !1, S.identity());
                        for (var f = 0; f < e.meshRenderables.length; ++f) {
                            var m = e.meshRenderables[f],
                                p = m.material;
                            !m.mesh.desc.castShadows || !p.castShadows || 0 < p.shadowAlphaTest || (h && i.uniformMatrix4fv(u.params.uMeshTransform, !1, m.mesh.displayMatrix),
                                m.drawShadow(u.attribs.vPosition))
                        }
                        for ((u = this.shaderAlphaTest).bind(),
                            i.uniformMatrix4fv(u.params.uViewProjection, !1, l),
                            i.uniformMatrix4fv(u.params.uMeshTransform, !1, S.identity()),
                            f = 0; f < e.meshRenderables.length; ++f)
                            p = (m = e.meshRenderables[f]).material,
                            m.mesh.desc.castShadows && p.castShadows && 0 < p.shadowAlphaTest && (p.textures.albedo.bind(u.samplers.tAlbedo),
                                h && (i.uniform2f(u.params.uUVOffset, p.uOffset, p.vOffset),
                                    i.uniformMatrix4fv(u.params.uMeshTransform, !1, m.mesh.displayMatrix)),
                                m.drawAlphaShadow(u.attribs.vPosition, u.attribs.vTexCoord))
                    }
                d && (t.bind(),
                    i.enable(i.CULL_FACE),
                    i.cullFace(i.BACK))
            },
            E.prototype.complete = function () {
                return this.shaderSolid.complete() && this.shaderAlphaTest.complete()
            },
            B.prototype.draw = function (e) {
                var t = e.view,
                    i = e.lights,
                    s = e.shadow,
                    n = this.gl,
                    r = this.shader.params,
                    a = this.shader.samplers;
                this.shader.bind(),
                    t = S.mul(S.empty(), t.projectionMatrix, t.viewMatrix),
                    S.mul(t, t, this.desc.transform),
                    n.uniformMatrix4fv(r.uModelViewProjectionMatrix, !1, t),
                    t = S.mul(S.empty(), i.matrix, this.desc.transform),
                    n.uniformMatrix4fv(r.uModelSkyMatrix, !1, t),
                    0 < i.count && (n.uniform4fv(r.uLightPositions, i.positionBuffer),
                        n.uniform3fv(r.uLightDirections, i.directionBuffer),
                        n.uniform3fv(r.uLightColors, i.colors),
                        n.uniform3fv(r.uLightParams, i.parameters),
                        n.uniform3fv(r.uLightSpot, i.spot),
                        e = .392699 * e.postRender.currentSample(),
                        n.uniform2f(r.uShadowKernelRotation, .5 * Math.cos(e), .5 * Math.sin(e)),
                        0 < i.shadowCount && (e = s.depthTextures[0].desc.width,
                            n.uniform2f(r.uShadowMapSize, e, 1 / e),
                            n.uniformMatrix4fv(r.uShadowMatrices, !1, i.finalTransformBuffer),
                            n.uniformMatrix4fv(r.uInvShadowMatrices, !1, i.inverseTransformBuffer),
                            n.uniform4fv(r.uShadowTexelPadProjections, i.shadowTexelPadProjections),
                            s.bindDepthTexture(a.tDepth0, 0),
                            s.bindDepthTexture(a.tDepth1, 1),
                            s.bindDepthTexture(a.tDepth2, 2))),
                    n.uniform3f(r.uShadowCatcherParams, this.desc.simple ? 1 : 0, this.desc.alpha, this.desc.edgeFade),
                    n.depthMask(!1),
                    n.enable(n.BLEND),
                    n.blendFunc(n.ZERO, n.SRC_COLOR),
                    i = this.shader.attribs.vPosition,
                    n.bindBuffer(n.ARRAY_BUFFER, this.quadGeom),
                    n.enableVertexAttribArray(i),
                    n.vertexAttribPointer(i, 3, n.FLOAT, !1, 0, 0),
                    n.drawArrays(n.TRIANGLES, 0, 6),
                    n.disableVertexAttribArray(i),
                    n.bindBuffer(n.ARRAY_BUFFER, null),
                    n.disable(n.BLEND),
                    n.depthMask(!0)
            },
            B.prototype.complete = function () {
                return this.shader.complete()
            },
            L.prototype.solveAdditiveClusterTransform = function (e, t, i) {
                t = S.identity();
                var s = S.identity(),
                    n = S.identity();
                S.mul(t, e, this.defaultClusterBaseTransform),
                    S.mul(s, this.defaultAssociateWorldTransformInvert, t),
                    S.mul(n, this.defaultAssociateWorldTransformInvert, s),
                    S.mul(i, this.defaultClusterWorldTransformInvert, n)
            },
            L.prototype.solveSimpleClusterTransform = function (e, t, i) {
                var s = S.identity(),
                    n = S.identity();
                S.invert(n, t),
                    S.mul(s, n, e),
                    S.mul(i, s, this.defaultClusterBaseTransform)
            },
            L.prototype.solveClusterTransformAtFrame = function (e, t, i, s) {
                if (1 == this.linkMode) {
                    var n = S.identity();
                    t = S.identity(),
                        e.evaluateModelPartTransformAtFrame(this.linkObjectIndex, i, n, !1),
                        e.evaluateModelPartTransformAtFrame(this.associateObjectIndex, i, t, !1),
                        this.solveAdditiveClusterTransform(n, t, s)
                } else {
                    n = S.identity();
                    var r = S.identity();
                    e.evaluateModelPartTransformAtFrame(this.linkObjectIndex, i, n, !1),
                        e.evaluateModelPartTransformAtFrame(t, i, r, !1),
                        this.solveSimpleClusterTransform(n, r, s)
                }
            },
            M.prototype.unpackUnitVectors = function (e, t, i, s) {
                for (var n = 0; n < i; n++) {
                    var r = t[s * n],
                        a = 32768 <= (o = t[s * n + 1]);
                    a && (o -= 32768);
                    var o, h = 1 - ((r = r / 32767.4 * 2 - 1) * r + (o = o / 32767.4 * 2 - 1) * o);
                    h = Math.sqrt(h),
                        h = isNaN(h) ? 0 : h;
                    a && (h = -h),
                        e[3 * n] = r,
                        e[3 * n + 1] = o,
                        e[3 * n + 2] = h
                }
            },
            M.prototype.copyOriginalVertices = function (e) {
                if (!this.unTransformedVertices)
                    if (this.unTransformedVertices = new Float32Array(3 * e.vertexCount),
                        this.unTransformedNormals = new Float32Array(3 * e.vertexCount),
                        this.unTransformedTangents = new Float32Array(3 * e.vertexCount),
                        this.unTransformedBiTangents = new Float32Array(3 * e.vertexCount),
                        this.skinVertexWeights = new Float32Array(e.vertexCount),
                        this.skinVertexTransform4x3 = new Float32Array(12),
                        e.dynamicVertexData) {
                        var t = new Float32Array(e.dynamicVertexData.buffer);
                        new Uint8Array(e.dynamicVertexData.buffer);
                        var i = s = 0,
                            s = s + 12 + 8;
                        e.secondaryTexCoord && (s += 8);
                        var n = s,
                            r = s += 4,
                            a = (s = s + 4,
                                e.stride / 2);
                        s = new Uint8Array(e.dynamicVertexData.subarray(s)),
                            s = new Uint16Array(s.buffer),
                            n = new Uint8Array(e.dynamicVertexData.subarray(n)),
                            n = new Uint16Array(n.buffer),
                            r = new Uint8Array(e.dynamicVertexData.subarray(r)),
                            r = new Uint16Array(r.buffer);
                        for (this.unpackUnitVectors(this.unTransformedNormals, s, e.vertexCount, a),
                            this.unpackUnitVectors(this.unTransformedTangents, n, e.vertexCount, a),
                            this.unpackUnitVectors(this.unTransformedBiTangents, r, e.vertexCount, a),
                            a = 0; a < e.vertexCount; a++)
                            r = (e.stride * a + i) / 4,
                            this.unTransformedVertices[3 * a] = t[r],
                            this.unTransformedVertices[3 * a + 1] = t[r + 1],
                            this.unTransformedVertices[3 * a + 2] = t[r + 2]
                    } else
                        this.debugString += "<br>Can't init skinning rig - mesh buffer is not dynamic - rigid is " + this.isRigidSkin
            },
            M.prototype.useOriginalMeshVertices = function (e) {
                this.isRigidSkin ? this.debugString += "<br>useOriginalMeshVertices for rigid skin?" : this.copyOriginalVertices(e)
            },
            M.prototype.deformMeshVertices = function (e, t) {
                if (0 != this.skinningClusters.length && this.unTransformedVertices) {
                    var i, s = e.stride / 4,
                        n = new Float32Array(e.dynamicVertexData.buffer),
                        r = new Uint16Array(e.dynamicVertexData.buffer);
                    new Uint8Array(e.dynamicVertexData.buffer),
                        i = 20,
                        e.secondaryTexCoord && (i += 8);
                    var a = i,
                        o = i += 4;
                    i += 4;
                    for (var h = this.unTransformedVertices.length / 3, l = 0, d = 0; d < h; ++d) {
                        var c = d,
                            u = (c * e.stride + a) / 2,
                            f = (c * e.stride + o) / 2,
                            m = (c * e.stride + i) / 2,
                            p = this.linkMapCount[c];
                        (k = this.skinVertexTransform4x3)[this.skinVertexWeights[c] = 0] = 0,
                        k[1] = 0,
                            k[2] = 0,
                            k[3] = 0,
                            k[4] = 0,
                            k[5] = 0,
                            k[6] = 0,
                            k[7] = 0,
                            k[8] = 0,
                            k[9] = 0,
                            k[10] = 0,
                            k[11] = 0;
                        var g = this.linkMapWeights[l];
                        if (1 == p && 1 == g) {
                            var v = this.linkMapClusterIndices[l],
                                x = (v = this.skinningClusters[v]).matrix;
                            k[0] = x[0],
                                k[1] = x[1],
                                k[2] = x[2],
                                k[3] = x[4],
                                k[4] = x[5],
                                k[5] = x[6],
                                k[6] = x[8],
                                k[7] = x[9],
                                k[8] = x[10],
                                k[9] = x[12],
                                k[10] = x[13],
                                k[11] = x[14],
                                this.skinVertexWeights[c] = 1
                        } else
                            for (var y = this.skinVertexWeights[c] = 0; y < p; y++)
                                g = this.linkMapWeights[l + y],
                                (v = this.linkMapClusterIndices[l + y]) < this.skinningClusters.length && (x = (v = this.skinningClusters[v]).matrix,
                                    k[0] += g * x[0],
                                    k[1] += g * x[1],
                                    k[2] += g * x[2],
                                    k[3] += g * x[4],
                                    k[4] += g * x[5],
                                    k[5] += g * x[6],
                                    k[6] += g * x[8],
                                    k[7] += g * x[9],
                                    k[8] += g * x[10],
                                    k[9] += g * x[12],
                                    k[10] += g * x[13],
                                    k[11] += g * x[14],
                                    this.skinVertexWeights[c] += g,
                                    1 == v.linkMode && (this.skinVertexWeights[c] = 1));
                        if (l += this.linkMapCount[d],
                            0 < this.skinVertexWeights[c]) {
                            var b = this.unTransformedVertices[3 * d + 0],
                                S = this.unTransformedVertices[3 * d + 1],
                                T = this.unTransformedVertices[3 * d + 2],
                                w = this.unTransformedNormals[3 * d + 0],
                                C = this.unTransformedNormals[3 * d + 1],
                                R = this.unTransformedNormals[3 * d + 2],
                                A = (v = this.unTransformedTangents[3 * d + 0],
                                    x = this.unTransformedTangents[3 * d + 1],
                                    this.unTransformedTangents[3 * d + 2]),
                                k = (p = this.unTransformedBiTangents[3 * d + 0],
                                    this.unTransformedBiTangents[3 * d + 1]),
                                I = (g = this.unTransformedBiTangents[3 * d + 2],
                                    y = this.skinVertexTransform4x3,
                                    1);
                            0 < this.skinVertexWeights[c] && (I = 1 / this.skinVertexWeights[c]),
                                n[s * d] = I * (b * y[0] + S * y[3] + T * y[6] + y[9]) * t,
                                n[s * d + 1] = I * (b * y[1] + S * y[4] + T * y[7] + y[10]) * t,
                                n[s * d + 2] = I * (b * y[2] + S * y[5] + T * y[8] + y[11]) * t,
                                b = w * y[0] + C * y[3] + R * y[6],
                                c = w * y[1] + C * y[4] + R * y[7],
                                w = w * y[2] + C * y[5] + R * y[8],
                                C = v * y[0] + x * y[3] + A * y[6],
                                R = v * y[1] + x * y[4] + A * y[7],
                                v = v * y[2] + x * y[5] + A * y[8],
                                x = p * y[0] + k * y[3] + g * y[6],
                                A = p * y[1] + k * y[4] + g * y[7],
                                p = p * y[2] + k * y[5] + g * y[8],
                                c /= k = Math.sqrt(b * b + c * c + w * w),
                                w /= k,
                                k = 32767.4 * ((b /= k) / 2 + .5),
                                g = 32767.4 * (c / 2 + .5),
                                w < 0 && (g += 32768),
                                r[m] = Math.floor(k),
                                r[1 + m] = Math.floor(g),
                                R /= k = Math.sqrt(C * C + R * R + v * v),
                                v /= k,
                                k = 32767.4 * ((C /= k) / 2 + .5),
                                g = 32767.4 * (R / 2 + .5),
                                v < 0 && (g += 32768),
                                r[u] = Math.floor(k),
                                r[1 + u] = Math.floor(g),
                                A /= k = Math.sqrt(x * x + A * A + p * p),
                                p /= k,
                                k = 32767.4 * ((x /= k) / 2 + .5),
                                g = 32767.4 * (A / 2 + .5),
                                p < 0 && (g += 32768),
                                r[f] = Math.floor(k),
                                r[1 + f] = Math.floor(g)
                        } else
                            b = this.unTransformedVertices[3 * d + 0],
                            S = this.unTransformedVertices[3 * d + 1],
                            T = this.unTransformedVertices[3 * d + 2],
                            n[s * d] = b * t,
                            n[s * d + 1] = S * t,
                            n[s * d + 2] = T * t
                    }
                }
            },
            M.prototype.deformMesh = function (e, t) {
                if (0 != this.skinningClusters.length && !this.isRigidSkin) {
                    this.deformMeshVertices(e, t);
                    var i = e.gl;
                    i.bindBuffer(i.ARRAY_BUFFER, e.vertexBuffer),
                        i.bufferData(i.ARRAY_BUFFER, e.dynamicVertexData, i.DYNAMIC_DRAW),
                        i.bindBuffer(i.ARRAY_BUFFER, null)
                }
            },
            _.prototype.setClearColor = function () {
                if (I.transparentBackground)
                    this.gl.clearColor(0, 0, 0, 0);
                else if (this.backgroundMode < 1) {
                    var e = this.backgroundColor;
                    this.gl.clearColor(e[0], e[1], e[2], 1)
                } else
                    this.gl.clearColor(.0582, .06772, .07805, 1)
            },
            _.prototype.draw = function (e) {
                if (this.backgroundMode < 1 || I.transparentBackground)
                    return !1;
                if (this.complete()) {
                    var t = this.gl,
                        i = this.backgroundShader,
                        s = e.view,
                        n = e.lights.invMatrix;
                    i.bind(),
                        t.uniformMatrix4fv(i.params.uInverseSkyMatrix, !1, n),
                        t.uniformMatrix4fv(i.params.uViewProjection, !1, s.viewProjectionMatrix),
                        3 == this.backgroundMode ? t.uniform4fv(i.params.uSkyCoefficients, this.backgroundCoefficients) : this.backgroundTexture.bind(i.samplers.tSkyTexture),
                        e = .07 + .94 * (1 - e.stripData.activeFade()),
                        t.uniform1f(i.params.uAlpha, e),
                        t.bindBuffer(t.ARRAY_BUFFER, this.vertexBuffer),
                        t.enableVertexAttribArray(i.attribs.vPosition),
                        t.vertexAttribPointer(i.attribs.vPosition, 3, t.FLOAT, !1, 20, 0),
                        t.enableVertexAttribArray(i.attribs.vTexCoord),
                        t.vertexAttribPointer(i.attribs.vTexCoord, 2, t.FLOAT, !1, 20, 12),
                        t.bindBuffer(t.ELEMENT_ARRAY_BUFFER, this.indexBuffer),
                        e < 1 && (t.enable(t.BLEND),
                            t.blendFunc(t.SRC_ALPHA, t.ONE_MINUS_SRC_ALPHA)),
                        t.depthMask(!1),
                        t.disable(t.DEPTH_TEST),
                        t.drawElements(t.TRIANGLES, this.skyIndexCount, t.UNSIGNED_SHORT, 0),
                        t.enable(t.DEPTH_TEST),
                        t.depthMask(!0),
                        e < 1 && t.disable(t.BLEND),
                        t.disableVertexAttribArray(i.attribs.vPosition),
                        t.disableVertexAttribArray(i.attribs.vTexCoord)
                }
            },
            _.prototype.complete = function () {
                return !(this.backgroundShader && !this.backgroundShader.complete()) && this.specularTexture.complete()
            },
            D.expDecay = function (e, t) {
                return Math.exp(-.69314718 / e * t)
            },
            D.prototype.update = function (e) {
                var t = .001 * (Date.now() - this.timestamp);
                this.timestamp = Date.now();
                for (var i = !1, s = 0; s < this.stripCount; ++s) {
                    var n = this.selectedStrip == this.STRIP_MENU ? .3 * (s + 1) - .9 : this.selectedStrip < 0 || s < this.selectedStrip ? -2 : 2;
                    if (e)
                        this.strips[s] = n;
                    else {
                        var r = (r = n - this.strips[s]) * D.expDecay(.05, t);
                        this.animationActive && (this.strips[s] = n - r),
                            i = i || .001 < Math.abs(r)
                    }
                }
                this.animationActive = i
            },
            D.prototype.active = function () {
                return this.selectedStrip >= this.STRIP_MENU
            },
            D.prototype.activeFade = function () {
                var e;
                return (e = 1 < (e = (this.strips[this.stripCount - 1] - -2) / (.3 * this.stripCount - .9 - -2)) ? 1 : e) < 0 ? 0 : e
            },
            D.prototype.activeWireframe = function () {
                return this.active() && .01 < Math.abs(this.strips[4] - this.strips[3])
            },
            D.prototype.toggleMenu = function () {
                this.selectedStrip = this.selectedStrip == this.STRIP_MENU ? this.STRIP_NONE : this.STRIP_MENU
            },
            D.prototype.selectStrip = function (e, t) {
                if (this.selectedStrip == this.STRIP_MENU) {
                    var i = e + t * this.stripSlant;
                    this.selectedStrip = this.STRIP_NONE;
                    for (var s = 0; s < this.stripCount; ++s)
                        if (i < this.strips[s]) {
                            this.selectedStrip = s;
                            break
                        }
                } else
                    this.selectedStrip = this.STRIP_MENU
            },
            U.prototype.loadImage = function (e, t) {
                var i = this.gl;
                e && e.width && e.height && (this.desc.width = e.width,
                        this.desc.height = e.height),
                    this.id = i.createTexture(),
                    i.bindTexture(this.type, this.id),
                    this.format = t || i.RGBA,
                    this.componentType = i.UNSIGNED_BYTE,
                    i.pixelStorei(i.UNPACK_FLIP_Y_WEBGL, !0),
                    i.texImage2D(this.type, 0, this.format, this.format, this.componentType, e),
                    this.setParams(),
                    i.bindTexture(this.type, null)
            },
            U.prototype.loadArray = function (e, t, i) {
                var s = this.gl;
                this.id = s.createTexture(),
                    s.bindTexture(this.type, this.id),
                    this.format = t || s.RGBA,
                    this.componentType = i || s.UNSIGNED_BYTE,
                    s.pixelStorei(s.UNPACK_FLIP_Y_WEBGL, !0),
                    s.texImage2D(this.type, 0, this.format, this.desc.width, this.desc.height, 0, this.format, this.componentType, e || null),
                    this.setParams(),
                    s.bindTexture(this.type, null)
            },
            U.prototype.setParams = function () {
                var e = this.gl,
                    t = function (e) {
                        return 0 < e && 0 == (e & e - 1)
                    };
                t(this.desc.width) && t(this.desc.height) || (this.desc.clamp = !0,
                        this.desc.mipmap = !1),
                    t = !this.desc.nofilter,
                    this.desc.mipmap ? (e.generateMipmap(this.type),
                        e.texParameteri(this.type, e.TEXTURE_MIN_FILTER, t ? e.LINEAR_MIPMAP_LINEAR : e.NEAREST_MIPMAP_NEAREST)) : e.texParameteri(this.type, e.TEXTURE_MIN_FILTER, t ? e.LINEAR : e.NEAREST),
                    e.texParameteri(this.type, e.TEXTURE_MAG_FILTER, t ? e.LINEAR : e.NEAREST),
                    (this.desc.clamp || this.desc.mirror) && (t = this.desc.clamp ? e.CLAMP_TO_EDGE : e.MIRRORED_REPEAT,
                        e.texParameteri(this.type, e.TEXTURE_WRAP_S, t),
                        e.texParameteri(this.type, e.TEXTURE_WRAP_T, t)),
                    this.desc.aniso && e.ext.textureAniso && e.texParameteri(this.type, e.ext.textureAniso.TEXTURE_MAX_ANISOTROPY_EXT, this.desc.aniso)
            },
            U.prototype.rebuildMips = function () {
                this.desc.mipmap && (this.gl.bindTexture(this.type, this.id),
                    this.gl.generateMipmap(this.type))
            },
            U.prototype.copyColorBuffer = function () {
                this.gl.bindTexture(this.type, this.id),
                    this.gl.copyTexSubImage2D(this.type, 0, 0, 0, 0, 0, this.desc.width, this.desc.height)
            },
            U.prototype.bind = function (e) {
                if (e) {
                    var t = this.gl;
                    t.uniform1i(e.location, e.unit),
                        t.activeTexture(t.TEXTURE0 + e.unit),
                        t.bindTexture(this.type, this.id)
                }
            },
            U.prototype.destroy = function () {
                this.gl.deleteTexture(this.id),
                    this.id = null
            },
            U.prototype.complete = function () {
                return !!this.id
            },
            N.prototype.fromURL = function (e, t) {
                var i = this.cache[e];
                if (void 0 !== i)
                    return i;
                var s = new U(this.gl, t);
                return C.fetchImage(e, function (e) {
                        s.loadImage(e)
                    }),
                    this.cache[e] = s
            },
            N.prototype.fromFile = function (e, t) {
                if (!e)
                    return null;
                var i = this.cache[e.name];
                if (void 0 !== i)
                    return i;
                var s = new U(this.gl, t);
                return this.cache[e.name] = s,
                    N.parseFile(e, function (e) {
                        s.loadImage(e),
                            N.closeImage(e)
                    }),
                    s
            },
            N.prototype.fromFilesMergeAlpha = function (e, t, i) {
                if (!t)
                    return this.fromFile(e, i);
                var s = e.name + "|" + t.name,
                    n = this.cache[s];
                if (void 0 !== n)
                    return n;
                var r = this.gl;
                this.blitShader || (this.blitShader = new F(this.gl),
                    this.blitShader.build("precision highp float; varying vec2 c; attribute vec2 pos; void main(){ gl_Position.xy = 2.0*pos-vec2(1.0); gl_Position.zw = vec2(0.5,1.0); c=pos; }", "precision highp float; varying vec2 c; uniform sampler2D tTex; void main(){ gl_FragColor=texture2D(tTex,c).rgbr; }"),
                    this.mergeVerts = r.createBuffer(),
                    r.bindBuffer(r.ARRAY_BUFFER, this.mergeVerts),
                    n = new Float32Array([0, 0, 2, 0, 0, 2]),
                    r.bufferData(r.ARRAY_BUFFER, n, r.STATIC_DRAW),
                    r.bindBuffer(r.ARRAY_BUFFER, null));
                var a = function (e) {
                        this.blitShader.bind(),
                            e.bind(this.blitShader.samplers.tTex),
                            r.bindBuffer(r.ARRAY_BUFFER, this.mergeVerts),
                            r.enableVertexAttribArray(this.blitShader.attribs.pos),
                            r.vertexAttribPointer(this.blitShader.attribs.pos, 2, r.FLOAT, !1, 0, 0),
                            r.drawArrays(r.TRIANGLES, 0, 3),
                            r.disableVertexAttribArray(this.blitShader.attribs.pos),
                            r.bindBuffer(r.ARRAY_BUFFER, null)
                    }
                    .bind(this),
                    o = new U(this.gl, i);
                this.cache[s] = o;
                var h = 0,
                    l = 0,
                    d = function () {
                        if (h && l) {
                            var e, t;
                            if (t = l.width * l.height > h.width * h.height ? (e = l.width,
                                    l.height) : (e = h.width,
                                    h.height),
                                o.desc.width = e,
                                o.desc.height = t,
                                e <= r.limits.viewportSizes[0] && t <= r.limits.viewportSizes[1]) {
                                var i = {
                                    clamp: !0
                                };
                                h.width == e && h.height == t ? (o.loadImage(h, r.RGBA),
                                        e = new m(r, {
                                            color0: o,
                                            ignoreStatus: !0
                                        }),
                                        N.closeImage(h)) : ((t = new U(r, i)).loadImage(h, r.RGB),
                                        N.closeImage(h),
                                        o.loadArray(null),
                                        (e = new m(r, {
                                            color0: o,
                                            ignoreStatus: !0
                                        })).bind(),
                                        a(t),
                                        t.destroy()),
                                    (t = new U(r, i)).loadImage(l, r.RGB),
                                    N.closeImage(l),
                                    e.bind(),
                                    r.colorMask(!1, !1, !1, !0),
                                    a(t),
                                    r.colorMask(!0, !0, !0, !0),
                                    t.destroy(),
                                    m.bindNone(r),
                                    o.rebuildMips()
                            } else {
                                (i = document.createElement("canvas")).width = e,
                                    i.height = t;
                                var s = i.getContext("2d");
                                for (s.drawImage(h, 0, 0),
                                    N.closeImage(h),
                                    i = s.getImageData(0, 0, e, t),
                                    i = new Uint8Array(i.data.buffer, i.data.byteOffset, i.data.length),
                                    s.drawImage(l, 0, 0),
                                    N.closeImage(l),
                                    s = s.getImageData(0, 0, e, t).data,
                                    e = e * t * 4,
                                    t = 0; t < e; t += 4)
                                    i[t + 3] = s[t];
                                o.loadArray(i)
                            }
                            N.closeImage(l)
                        }
                    };
                return N.parseFile(e, function (e) {
                        h = e,
                            d()
                    }),
                    N.parseFile(t, function (e) {
                        l = e,
                            d()
                    }),
                    o
            },
            N.parseFile = function (e, t, i) {
                var s = i || new Image();
                if ("undefined" != typeof URL && void 0 !== URL.createObjectURL) {
                    e = new Blob([e.data], {
                        type: e.type
                    });
                    var n = URL.createObjectURL(e);
                    s.onload = function () {
                            URL.revokeObjectURL(n),
                                t && t(s)
                        },
                        s.src = n
                } else {
                    e = new Blob([e.data], {
                        type: e.type
                    });
                    var r = new FileReader();
                    r.onload = function (e) {
                            s.src = r.result
                        },
                        s.onload = function () {
                            t && t(s)
                        },
                        r.readAsDataURL(e)
                }
            },
            N.closeImage = function (e) {
                e && 256 < e.width * e.height && (e.onload = null,
                    e.onerror = null,
                    e.src = "data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D")
            },
            z.prototype.setBackground3x1 = function (e, t, i, s) {
                var n = 8 / this.controlRect.getScreenHeight();
                this.backgroundControl = e.addTextButton("", 0, (1 - n) / 2, 1, n, 1),
                    this.backgroundControl.defaultAlpha = 1,
                    this.backgroundControl.setBackground3x1(e, 0, 0, t, i, s, 4),
                    this.backgroundControl.controlRect.xPercent = this.controlRect.xPercent,
                    this.backgroundControl.controlRect.widthPercent = this.controlRect.widthPercent,
                    this.controlRect.linkedControl.style.zIndex = "3",
                    this.setupCallbacks()
            },
            z.prototype.setSize = function (e, t) {
                this.pixelsX = e;
                var i = 24 / (this.pixelsY = t);
                this.knobWidthPercent = 24 / e,
                    this.knobControlRect.xPercent = .5 - this.knobWidthPercent / 2,
                    this.knobControlRect.yPercent = (1 - i) / 2 + -1 / t,
                    this.knobControlRect.widthPercent = this.knobWidthPercent,
                    this.knobControlRect.heightPercent = i,
                    this.controlRect.updateElement(),
                    this.backgroundControl.controlRect.xPercent = this.controlRect.xPercent,
                    this.backgroundControl.controlRect.widthPercent = this.controlRect.widthPercent,
                    this.backgroundControl.controlRect.updateElement()
            },
            z.prototype.setSliderPercent = function (e) {
                e < 0 && (e = 0),
                    1 < e && (e = 1),
                    this.sliderPercent = e,
                    this.knobControlRect.xPercent = e - this.knobWidthPercent / 2,
                    this.knobControlRect.updateElement()
            },
            z.prototype.setupCallbacks = function () {
                var e = function (e) {
                        if (this.draggingSlider) {
                            var t = this.backgroundControl.controlRect.linkedControl.getBoundingClientRect();
                            this.setSliderPercent((e.clientX - t.left) / t.width),
                                this.guiScreen.ui.viewer.scene.sceneAnimator.setAnimationProgress(this.sliderPercent, !0),
                                this.guiScreen.ui.viewer.scene.sceneAnimator.paused && (this.guiScreen.ui.viewer.scene.postRender.discardAAHistory(),
                                    this.guiScreen.ui.viewer.reDrawScene())
                        }
                    }
                    .bind(this),
                    t = function (e) {
                        this.draggingSlider = !0;
                        var t = this.backgroundControl.controlRect.linkedControl.getBoundingClientRect();
                        this.setSliderPercent((e.clientX - t.left) / t.width),
                            this.guiScreen.ui.viewer.scene.sceneAnimator.setAnimationProgress(this.sliderPercent, !0),
                            this.guiScreen.ui.viewer.scene.sceneAnimator.lockPlayback = !0,
                            this.guiScreen.ui.viewer.scene.sceneAnimator.paused && (this.guiScreen.ui.viewer.scene.postRender.discardAAHistory(),
                                this.guiScreen.ui.viewer.reDrawScene())
                    }
                    .bind(this),
                    i = function (e) {
                        this.draggingSlider = !1,
                            this.guiScreen.ui.viewer.scene.sceneAnimator.lockPlayback = !1
                    }
                    .bind(this);
                this.guiScreen.ui.viewer.input.element.addEventListener("mousemove", e),
                    this.guiScreen.ui.viewer.input.element.addEventListener("mouseup", i),
                    this.backgroundControl.controlRect.linkedControl.addEventListener("mousemove", e),
                    this.backgroundControl.controlRect.linkedControl.addEventListener("mousedown", t),
                    this.backgroundControl.controlRect.linkedControl.addEventListener("mouseup", i),
                    this.controlRect.linkedControl.addEventListener("mouseup", i)
            },
            j.prototype.setSize = function (e, t) {
                this.container.width = 0 | e,
                    this.container.height = 0 | t,
                    this.container.style.width = e + "px",
                    this.container.style.height = t + "px",
                    this.guiScreen.setSize(this.container.width, this.container.height)
            },
            j.prototype.clearView = function () {
                for (; this.container.hasChildNodes();)
                    this.container.removeChild(this.container.childNodes[0]);
                delete this.progressBar,
                    delete this.thumbnail,
                    delete this.fadeThumbnail,
                    delete this.playButton,
                    delete this.helpOverlay
            },
            j.prototype.bindInput = function (i) {
                i.onSingleTap.push(function (e, t) {
                        this.stripData.selectedStrip != this.stripData.STRIP_NONE && (e = 2 / i.element.clientWidth * e - 1,
                            t = 1 - 2 / i.element.clientHeight * t,
                            this.stripData.selectStrip(e, t),
                            this.stripData.selectedStrip == this.stripData.STRIP_MENU && this.helpOverlay.active && this.helpOverlay.toggle(),
                            this.refreshUI(),
                            this.viewer.wake())
                    }
                    .bind(this))
            },
            j.sanitize = function (e) {
                return e ? e.replace(/<|>|\(|\)|$|%|=/g, "") : e
            },
            j.sanitizeURL = function (e) {
                return e ? 0 == e.indexOf("http://") || 0 == e.indexOf("https://") || 0 == e.indexOf("ftp://") ? encodeURI(e) : "http://" + encodeURI(e) : e
            },
            j.prototype.showFailure = function (e, t) {
                this.container.innerHTML = "";
                var i = document.createElement("canvas"),
                    s = this.container.width / this.container.height;
                i.width = 100,
                    i.height = i.height * s | 0,
                    i.style.position = "absolute",
                    i.style["z-index"] = "0",
                    i.style.width = i.style.height = "100%";
                var n = i.getContext("2d"),
                    r = n.fillStyle = n.createRadialGradient(i.width / 2, i.height / 2, (i.width + i.height) / 2, i.width / 2, i.height / 2, 0);
                r.addColorStop(0, "rgb(0,0,0)"),
                    r.addColorStop(1, "rgb(35,60,80)"),
                    n.fillStyle = r,
                    n.fillRect(0, 0, i.width, i.height),
                    this.container.appendChild(i);
                var a = document.createElement("div");
                dom.addClass(a, "error"),
                    a.style["background-image"] = "url(images/errorBG.png)";
                var o = '<div class="errorInfo"><p style="font-size:1.5em; font-weight:lighter">转换模型时出错</p><p style="font-size:1.3em;letter-spacing:2px;font-weight:bold;line-height:1.5em;margin-top:30px">错误信息: ' + (e || "文件无效(ERROR)请检查您所上传的文件以确定其稳定性") + '</p><p style="font-size:0.8em;line-height:1.5em; margin-top:50px">您可以联系我们的客服、或点击<a href="http://www.4dage.com/tutorial.html" style="color: #a6ccea;">视频教程</a>获取更详细的上传解说<br>4Dweb将全程为您提供最优质的模型展示</p></div>';
                a.innerHTML = o,
                    this.container.appendChild(a)
            },
            j.prototype.showPreview = function (e) {
                this.clearView(),
                //去掉封面
                   /*  this.thumbnail = document.createElement("canvas");
                var t = this.container.width / this.container.height;
                this.thumbnail.height = this.viewer.mobile ? 200 : 300,
                    this.thumbnail.width = this.thumbnail.height * t | 0,
                    this.thumbnail.style.width = this.thumbnail.style.height = "100%";
                var i = (t = this.thumbnail.getContext("2d")).fillStyle = t.createRadialGradient(this.thumbnail.width / 2, this.thumbnail.height / 2, (this.thumbnail.width + this.thumbnail.height) / 2, this.thumbnail.width / 2, 0, 0);
                i.addColorStop(0, "rgb(0,0,0)"),
                    i.addColorStop(1, "rgb(7,62,92)"),
                    t.fillStyle = i,
                    t.fillRect(0, 0, this.thumbnail.width, this.thumbnail.height),
                    this.container.appendChild(this.thumbnail), */
                    this.playButton = document.createElement("input"),
                    this.playButton.type = "image",
                    // this.playButton.src = I.dataLocale + "play.png",
                    this.playButton.style.position = "absolute",
                    this.playButton.style.left = "50%",
                    this.playButton.style.top = "50%",
                    this.playButton.style["-webkit-transform"] = this.playButton.style.transform = "translate(-50%,-50%) scale(0.4,0.4)",
                    this.playButton.style.opacity = .5,
                    this.playButton.style.outline = "0px",
                    this.playButton.onclick = function () {
                        this.viewer.loadScene(this.viewer.sceneURL),
                            this.container.removeChild(this.playButton),
                            delete this.playButton
                    }
                    .bind(this),
                    this.container.appendChild(this.playButton),
                    e || n(this.viewer.sceneURL, function (e) {
                            this.loadingImageURL || this.setThumbnail(e)
                        }
                        .bind(this))
            },
            j.prototype.setThumbnailURL = function (e) {
                (this.loadingImageURL = e) && C.fetchImage(this.loadingImageURL, this.setThumbnail.bind(this))
            },
            j.prototype.setThumbnail = function (e) {
                return//去掉封面
                if (this.thumbnail)
                    if (e.height >= this.container.height) {
                        var t = this.container.height / e.height;
                        e.style.position = "absolute",
                            e.style.outline = "0px",
                            e.style.left = "50%",
                            e.style.top = "50%",
                            e.style["-webkit-transform"] = e.style.transform = "translate(-50%,-50%) scale(" + t + "," + t + ")",
                            this.container.replaceChild(e, this.thumbnail),
                            this.thumbnail = e
                    } else {
                        var i, s = this.thumbnail.getContext("2d"),
                            n = this.thumbnail.width,
                            r = this.thumbnail.height;
                        t = r / e.height;
                        s.drawImage(e, (n - e.width * t) / 2, 0, e.width * t, r);
                        try {
                            i = s.getImageData(0, 0, n, r)
                        } catch (e) {
                            return
                        }
                        e = s.createImageData(n, r);
                        for (var a = 0; a < 2; ++a) {
                            t = i.data;
                            for (var o = e.data, h = 0, l = 0; l < r; ++l)
                                for (var d = 0; d < n; ++d) {
                                    for (var c = 0, u = 0, f = 0, m = -2; m <= 2; ++m)
                                        for (var p = (p = l + m) < 0 ? 0 : r <= p ? r - 1 : p, g = -2; g <= 2; ++g) {
                                            var v;
                                            c = c + t[v = 4 * (p * n + (v = (v = d + g) < 0 ? 0 : n <= v ? n - 1 : v))],
                                                u = u + t[v + 1],
                                                f = f + t[v + 2]
                                        }
                                    o[h++] = c / 25,
                                        o[h++] = u / 25,
                                        o[h++] = f / 25,
                                        o[h++] = 255
                                }
                            t = i,
                                i = e,
                                e = t
                        }
                        s.putImageData(i, 0, 0)
                    }
            },
            j.prototype.showActiveView = function () {
                var e, t, i, s, n, r = this.thumbnail;
                this.clearView(),
                    r && (this.fadeThumbnail = r,
                        this.fadeThumbnail.style.opacity = 1,
                        this.container.appendChild(this.fadeThumbnail)),
                    void 0 === I.largeUI && (I.largeUI = this.viewer.mobile),
                    this.container.width < 450 && (I.largeUI = !1);
                var a = g.support();
                r = 1;
                window.devicePixelRatio && (2 < window.devicePixelRatio ? r = 4 : 1 < window.devicePixelRatio && (r = 2)),
                    I.largeUI && r < 4 && (r *= 2);
                var o = I.largeUI ? .3 : .5;
                this.helpOverlay = document.createElement("div"),
                    this.helpOverlay.style.pointerEvents = "none",
                    this.container.appendChild(this.helpOverlay),
                    this.hideSigOnHelp = e = this.container.width < 450,
                    this.hideSigOnStrips = !0,
                    t = [8, 8],
                    s = e ? (i = 198 + 2 * t[0],
                        258 + 2 * t[1]) : (i = 354 + 2 * t[0],
                        218 + 2 * t[1]),
                    (n = document.createElement("div")).style.position = "absolute",
                    n.style.width = n.style.height = "100%",
                    this.helpOverlay.contents = n,
                    (n = document.createElement("div")).style.position = "absolute",
                    n.style.right = I.largeUI ? "85px" : "45px",
                    n.style.top = I.largeUI ? "20px" : "12px",
                    n.style["z-index"] = "20",
                    n.style.width = i + "px",
                    n.style.height = s + "px",
                    this.helpOverlay.contents.appendChild(n),
                    (s = document.createElement("div")).style.position = "absolute",
                    s.style.width = "100%",
                    s.style.height = "100%",
                    s.style.backgroundColor = "black",
                    s.style.opacity = "0.65",
                    s.style.borderRadius = "16px",
                    n.appendChild(s),
                    s = document.createElement("a"),
                    dom.addClass(s, "tipClose"),
                    s.style.position = "absolute",
                    s.style.color = "#FFFFFF",
                    s.style.backgroundColor = "rgba(0,0,0,0.0)",
                    s.style.border = "0px",
                    s.style.outline = "0px",
                    s.style.fontSize = I.largeUI ? "16pt" : "10pt",
                    s.style.right = I.largeUI ? "-9px" : "4px",
                    s.style.top = I.largeUI ? "3px" : "7px",
                    s.style.width = s.style.height = I.largeUI ? "32px" : "16px",
                    s.style.pointerEvents = "auto",
                    s.style.cursor = "pointer",
                    s.onclick = function (e) {
                        this.helpOverlay.toggle(),
                            this.refreshUI()
                    }
                    .bind(this, s),
                    n.appendChild(s),
                    (s = document.createElement("center")).style.position = "absolute",
                    s.style.left = t[0] - 4 + "px",
                    s.style.right = t[0] + 4 + "px",
                    s.style.top = s.style.bottom = t[1] + "px",
                    s.style.paddingTop = "8px",
                    e || (s.style.paddingRight = "8px"),
                    n.appendChild(s),
                    n = s,
                    t = (this.viewer.mobile ? "M" : "PC") + (2 < r ? 4 : 2) + "x.png",
                    (s = document.createElement("img")).style.width = "66px",
                    s.style.height = "90px",
                    n.appendChild(s),
                    (s = document.createElement("img")).style.width = "66px",
                    s.style.height = "90px",
                    n.appendChild(s),
                    (s = document.createElement("img")).style.width = "66px",
                    s.style.height = "90px",
                    n.appendChild(s),
                    (s = document.createElement("img")).style.width = "66px",
                    s.style.height = "90px",
                    n.appendChild(s),
                    (s = document.createElement("img")).style.position = "relative",
                    e || (s.style.left = "8px"),
                    s.style.width = "66px",
                    s.style.height = "90px",
                    n.appendChild(s),
                    (t = document.createElement("a")).href = "http://www.4dage.com/",
                    t.target = "_blank",
                    t.style.pointerEvents = "auto",
                    t.style.cursor = "pointer",
                    n.appendChild(t),
                    (s = document.createElement("img")).style.position = "absolute",
                    s.style.left = .5 * i - (e ? 65 : 116) + "px",
                    s.style.bottom = e ? "8px" : "12px",
                    s.style.width = e ? "116px" : "232px",
                    t.appendChild(s),
                    (i = document.createElement("div")).style.position = "absolute",
                    i.style.left = 0,
                    i.style.right = e ? "30px" : "128px",
                    i.style.bottom = e ? "-4px" : "4px",
                    i.style.textAlign = "right",
                    i.style.fontFamilly = "Open Sans Arial",
                    n.appendChild(i),
                    (e = document.createElement("font")).style.fontSize = "9pt",
                    e.style.fontFamily = "Open Sans Arial",
                    i.appendChild(e),
                    e.appendChild(t),
                    this.helpOverlay.active = !1,
                    this.helpOverlay.toggle = function (e) {
                        this.active ? this.removeChild(this.contents) : this.appendChild(this.contents),
                            this.active = !this.active
                    }
                    .bind(this.helpOverlay, this.viewer),
                    this.menuCluster = document.createElement("div"),
                    this.menuCluster.style.position = "absolute",
                    this.menuCluster.style.right = I.largeUI ? "4px" : "0px",
                    this.menuCluster.style.top = I.largeUI ? "20px" : "10px",
                    I.largeUI ? (this.menuCluster.style.width = "72px",
                        this.menuCluster.style.height = "64px") : (this.menuCluster.style.width = "36px",
                        this.menuCluster.style.height = "36px"),
                    (n = document.createElement("div")).style.left = n.style.top = "0px",
                    n.style.width = n.style.height = "100%",
                    this.menuCluster.contents = n,
                    this.menuCluster.appendChild(n),
                    e = 0;
                var h = (i = function (e, t, i, s, n, r) {
                    var a = document.createElement("div");
                    return dom.addClass(a, "controlBtn"),
                        dom.addClass(a, i),
                        a.title = t,
                        I.largeUI && dom.addClass(a, "largeUI"),
                        e.appendChild(a),
                        a
                })(this.menuCluster.contents, "4DAGE主页", "home", "", e++, o);
                for (h.onclick = function (e) {
                        window.open("http://www.4dage.com", "_blank")
                    }
                    .bind(this, h),
                    a && ((a = i(this.menuCluster.contents, "全屏", "fullscreen", "fullscreen" + r + "x.png", e++, o)).onclick = function (e) {
                            g.active() ? g.end() : g.begin(this.viewer.domRoot, this.viewer.fullscreenChange.bind(this.viewer)),
                                dom.hasClass(e, "full") ? dom.removeClass(e, "full") : dom.addClass(e, "full"),
                                this.refreshUI()
                        }
                        .bind(this, a)),
                    (a = i(this.menuCluster.contents, "操作方式说明", "tips", "help" + r + "x.png", e++, o)).onclick = function (e) {
                        this.helpOverlay.toggle(),
                            this.refreshUI()
                    }
                    .bind(this, a),
                    this.container.appendChild(this.menuCluster),
                    this.menuCluster.active = !0,
                    this.menuCluster.toggle = function () {
                        this.active ? this.removeChild(this.contents) : this.appendChild(this.contents),
                            this.active = !this.active
                    }
                    .bind(this.menuCluster),
                    void 0 !== I.hostImage && (I.hostURL && ((t = document.createElement("a")).href = I.hostURL,
                            t.target = "_blank"),
                        (s = document.createElement("img")).src = I.hostImage,
                        s.style.position = "absolute",
                        s.style.top = "4px",
                        s.style.left = "4px",
                        s.style.opacity = .65,
                        s.style["-webkit-transform"] = s.style.transform = "translate(-50%,-50%) scale(0.5,0.5) translate(50%,50%)",
                        I.hostURL ? (s.onmouseover = function () {
                                this.style.opacity = 1
                            }
                            .bind(s),
                            s.onmouseout = function () {
                                this.style.opacity = .5
                            }
                            .bind(s),
                            t.appendChild(s),
                            this.hostLogo = t) : this.hostLogo = s,
                        (e = new XMLHttpRequest()).open("HEAD", s.src, !0),
                        e.onload = function () {
                            this.container.appendChild(this.hostLogo)
                        }
                        .bind(this),
                        e.send()),
                    this.sceneStats = document.createElement("text"),
                    this.sceneStats.style.position = "absolute",
                    this.sceneStats.style.left = "9px",
                    this.sceneStats.style.bottom = "8px",
                    this.sceneStats.style.color = "gray",
                    this.sceneStats.style.fontFamily = "Open Sans Arial",
                    this.sceneStats.style.fontSize = "75%",
                    e = a = r = 0; e < this.viewer.scene.meshes.length; ++e)
                    r += (i = this.viewer.scene.meshes[e]).indexCount / 3,
                    a += i.vertexCount;
                this.sceneStats.innerHTML = "Triangles: " + (0 | r).toLocaleString() + "<br>Vertices: " + (0 | a).toLocaleString(),
                    I.showFrameTime && (this.frameTimer = document.createElement("text"),
                        this.frameTimer.style.position = "absolute",
                        this.frameTimer.style.left = this.frameTimer.style.top = "5px",
                        this.frameTimer.style.color = "gray",
                        this.frameTimer.style.fontSize = "75%",
                        this.container.appendChild(this.frameTimer),
                        this.frameTimer.innerHTML = "--",
                        this.frameCount = 1e20)
            },
            j.prototype.refreshUI = function () {
                if (this.sigCluster) {
                    var e = !1,
                        t = this.stripData.selectedStrip == this.stripData.STRIP_MENU;
                    this.hideSigOnStrips && (e = e || t),
                        this.hideSigOnHelp && (e = e || this.helpOverlay.active),
                        this.sigCluster.active == e && this.sigCluster.toggle()
                }
            },
            j.prototype.signalLoadProgress = function (e, t) {
                //if (this.thumbnail) {
                    if (!this.progressBar) {
                        var i = document.createElement("div");
                        i.style.backgroundColor = "rgb(240,240,240)",
                            i.style.opacity = .9,
                            i.style.position = "absolute",
                            i.style.zIndex = 999
                        i.style.left = "20%",
                            i.style.width = "60%",
                            i.style.bottom = "30%",
                            i.style.height = "4px",
                            i.style["border-radius"] = "2px",
                            this.progressBar = document.createElement("div"),
                            this.progressBar.style.backgroundColor = "#00ccff",
                            this.progressBar.style.position = "absolute",
                            this.progressBar.style.left = this.progressBar.style.bottom = "0px",
                            this.progressBar.style.height = "100%",
                            this.progressBar.style.width = "0px",
                            this.progressBar.style["border-radius"] = "2px",
                            i.appendChild(this.progressBar),
                            this.container.appendChild(i),
                            this.playButton && (this.container.removeChild(this.playButton),
                                delete this.playButton)
                    }
                    this.progressBar.style.width = t <= 0 ? (100 * e / (2097152 + e) | 0) + "%" : (100 * e / t | 0) + "%"
                //}
            },
            j.prototype.animating = function () {
                return !!this.fadeThumbnail || !!this.frameTimer
            },
            j.prototype.animate = function () {
                if (this.fadeThumbnail && (this.fadeThumbnailTimer = this.fadeThumbnailTimer || Date.now(),
                        this.fadeThumbnail.style.opacity = 1 - .0015 * (Date.now() - this.fadeThumbnailTimer),
                        this.fadeThumbnail.style.opacity < .01 && (this.container.removeChild(this.fadeThumbnail),
                            delete this.fadeThumbnail,
                            delete this.fadeThumbnailTimer)),
                    this.frameTimer && (this.frameCount++,
                        60 <= this.frameCount)) {
                    var e = (new Date()).getTime();
                    if (void 0 !== this.frameTime) {
                        var t = (e - this.frameTime) / this.frameCount;
                        t = Math.floor(100 * t) / 100;
                        this.frameTimer.innerHTML = t + " ms",
                            this.frameTimer.style.color = t < 32 ? "green" : "red"
                    }
                    this.frameCount = 0,
                        this.frameTime = e
                }
                if (this.guiScreen && this.guiScreen.playbackControls && ((e = this.guiScreen.playbackControls.timelineSlider).draggingSlider ? this.viewer.scene.sceneAnimator.setAnimationProgress(e.sliderPercent, !0) : e.setSliderPercent(this.viewer.scene.sceneAnimator.animationProgress)),
                    this.sceneStats) {
                    for (var i = t = e = 0; i < this.viewer.scene.meshes.length; ++i) {
                        var s = this.viewer.scene.meshes[i];
                        e = e + s.indexCount / 3,
                            t = t + s.vertexCount
                    }
                    this.sceneStats.innerHTML = "Triangles: " + (0 | e).toLocaleString() + "<br>Vertices: " + (0 | t).toLocaleString(),
                        this.viewer.scene.sceneAnimator && this.viewer.scene.sceneAnimator.showPlayControls && (this.sceneStats.innerHTML += "<br><br><br><br>"),
                        e = !!this.sceneStats.parentElement,
                        t = this.stripData.active() || !1,
                        e && !t ? (this.container.removeChild(this.sceneStats),
                            this.hostLogo && this.container.appendChild(this.hostLogo)) : !e && t && (this.container.appendChild(this.sceneStats),
                            this.hostLogo && this.container.removeChild(this.hostLogo))
                }
                this.refreshUI(),
                    (this.stripData.animationActive || this.stripData.active()) && (this.animateStrips(),
                        this.stripData.animationActive && this.viewer.wake())
            },
            j.prototype.animateStrips = function () {
                if (this.stripText)
                    for (var e = Math.atan(this.viewer.canvas.height / this.viewer.canvas.width / this.stripData.stripSlant), t = 0; t < this.stripData.labels.length; ++t) {
                        var i = .5 + .5 * (i = (i = this.stripData.strips[t]) - this.stripData.stripSlant);
                        t == this.stripData.selectedStrip ? (this.stripText[t].style["-ms-transform"] = this.stripText[t].style["-webkit-transform"] = this.stripText[t].style.transform = "none",
                            this.stripText[t].style.top = "4px",
                            this.stripText[t].style.left = "0px",
                            this.stripText[t].style.width = "150px",
                            this.stripText[t].txt.style.textAlign = "center",
                            this.stripText[t].txt.style.background = "rgba(0, 0, 0, 0.75)",
                            this.stripText[t].txt.style.background = "-webkit-linear-gradient(left, rgba(0,0,0,0.75), rgba(0,0,0,0))",
                            this.stripText[t].txt.style.background = "-o-linear-gradient(left,      rgba(0,0,0,0.75), rgba(0,0,0,0))",
                            this.stripText[t].txt.style.background = "-moz-linear-gradient(left,    rgba(0,0,0,0.75), rgba(0,0,0,0))",
                            this.stripText[t].txt.style.background = "linear-gradient(left,         rgba(0,0,0,0.75), rgba(0,0,0,0))",
                            this.stripText[t].txt.style.paddingLeft = "32px",
                            this.stripText[t].txt.style.paddingTop = "6px",
                            this.stripText[t].txt.style.paddingBottom = "4px",
                            this.stripText[t].txt.style.textShadow = "1px 1px 2px rgba(0,0,0,0.7)",
                            this.stripText[t].line.style.opacity = .5,
                            this.stripText[t].line.style.top = "100%",
                            this.stripText[t].line.style.width = "100%",
                            this.stripText[t].line.style.height = "1px") : (this.stripText[t].style["-ms-transform"] = this.stripText[t].style["-webkit-transform"] = this.stripText[t].style.transform = "translate(-50%, -50%) rotate(" + e + "rad) translate(50%, 50%)",
                            this.stripText[t].style.left = 100 * i + "%",
                            this.stripText[t].style.top = "0px",
                            this.stripText[t].style.width = "85px",
                            this.stripText[t].txt.style.textAlign = "left",
                            this.stripText[t].txt.style.background = "none",
                            this.stripText[t].txt.style.paddingLeft = "8px",
                            this.stripText[t].txt.style.paddingTop = "6px",
                            this.stripText[t].txt.style.paddingBottom = "4px",
                            this.stripText[t].txt.style.textShadow = "2px 0px 3px rgba(0,0,0,0.7)",
                            this.stripText[t].line.style.opacity = 1,
                            this.stripText[t].line.style.top = "-1px",
                            this.stripText[t].line.style.width = "10000px",
                            this.stripText[t].line.style.height = "2px")
                    }
            };
        var V = {
            type: Float32Array,
            create: function (e, t, i, s) {
                var n = new V.type(4);
                return n[0] = e,
                    n[1] = t,
                    n[2] = i,
                    n[3] = s,
                    n
            },
            empty: function () {
                return new V.type(4)
            },
            set: function (e, t, i, s, n) {
                e[0] = t,
                    e[1] = i,
                    e[2] = s,
                    e[3] = n
            },
            copy: function (e, t) {
                e[0] = t[0],
                    e[1] = t[1],
                    e[2] = t[2],
                    e[3] = t[3]
            },
            add: function (e, t, i) {
                return e[0] = t[0] + i[0],
                    e[1] = t[1] + i[1],
                    e[2] = t[2] + i[2],
                    e[3] = t[3] + i[3],
                    e
            },
            sub: function (e, t, i) {
                return e[0] = t[0] - i[0],
                    e[1] = t[1] - i[1],
                    e[2] = t[2] - i[2],
                    e[3] = t[3] - i[3],
                    e
            },
            scale: function (e, t, i) {
                return e[0] = i[0] * t,
                    e[1] = i[1] * t,
                    e[2] = i[2] * t,
                    e[3] = i[3] * t,
                    e
            },
            mul: function (e, t, i) {
                return e[0] = t[0] * i[0],
                    e[1] = t[1] * i[1],
                    e[2] = t[2] * i[2],
                    e[3] = t[3] * i[3],
                    e
            },
            mad: function (e, t, i, s) {
                return e[0] = t[0] * i[0] + s[0],
                    e[1] = t[1] * i[1] + s[1],
                    e[2] = t[2] * i[2] + s[2],
                    e[3] = t[3] * i[3] + s[3],
                    e
            },
            smad: function (e, t, i, s) {
                return e[0] = t * i[0] + s[0],
                    e[1] = t * i[1] + s[1],
                    e[2] = t * i[2] + s[2],
                    e[3] = t * i[3] + s[3],
                    e
            },
            negate: function (e, t) {
                return e[0] = -t[0],
                    e[1] = -t[1],
                    e[2] = -t[2],
                    e
            },
            negate4: function (e, t) {
                return e[0] = -t[0],
                    e[1] = -t[1],
                    e[2] = -t[2],
                    e[3] = -t[3],
                    e
            },
            length: function (e) {
                var t = e[0],
                    i = e[1];
                return e = e[2],
                    Math.sqrt(t * t + i * i + e * e)
            },
            distance: function (e, t) {
                var i = e[0] - t[0],
                    s = e[1] - t[1],
                    n = e[2] - t[2];
                return Math.sqrt(i * i + s * s + n * n)
            },
            dot: function (e, t) {
                return e[0] * t[0] + e[1] * t[1] + e[2] * t[2]
            },
            dot4: function (e, t) {
                return e[0] * t[0] + e[1] * t[1] + e[2] * t[2] + e[3] * t[3]
            },
            normalize: function (e, t) {
                var i = t[0],
                    s = t[1],
                    n = t[2],
                    r = Math.sqrt(i * i + s * s + n * n);
                return 0 == r ? V.set(e, 0, 0, 0, 0) : (r = 1 / r,
                    e[0] = i * r,
                    e[1] = s * r,
                    e[2] = n * r,
                    e)
            },
            cross: function (e, t, i) {
                return e[0] = t[1] * i[2],
                    e[0] += -t[2] * i[1],
                    e[1] = t[2] * i[0] - t[0] * i[2],
                    e[2] = t[0] * i[1] - t[1] * i[0],
                    e
            },
            lerp: function (e, t, i, s) {
                var n = 1 - s;
                return e[0] = t[0] * n + i[0] * s,
                    e[1] = t[1] * n + i[1] * s,
                    e[2] = t[2] * n + i[2] * s,
                    e
            },
            lerp4: function (e, t, i, s) {
                var n = 1 - s;
                return e[0] = t[0] * n + i[0] * s,
                    e[1] = t[1] * n + i[1] * s,
                    e[2] = t[2] * n + i[2] * s,
                    e[3] = t[3] * n + i[3] * s,
                    e
            },
            min: function (e, t, i) {
                return e[0] = Math.min(t[0], i[0]),
                    e[1] = Math.min(t[1], i[1]),
                    e[2] = Math.min(t[2], i[2]),
                    e[3] = Math.min(t[3], i[3]),
                    e
            },
            max: function (e, t, i) {
                return e[0] = Math.max(t[0], i[0]),
                    e[1] = Math.max(t[1], i[1]),
                    e[2] = Math.max(t[2], i[2]),
                    e[3] = Math.max(t[3], i[3]),
                    e
            },
            projectOnPlane: function (e, t, i, s) {
                var n = V.empty();
                return V.sub(n, t, i),
                    i = V.dot(n, s),
                    smad(e, -i, normal, t),
                    e
            }
        };

        function H(e) {
            this.pivot = [0, 0, 0],
                this.rotation = [0, 0],
                this.radius = 1,
                this.nearPlane = .3,
                this.fov = 45,
                this.size = [1, 1],
                this.transform = S.empty(),
                this.viewMatrix = S.empty(),
                this.projectionMatrix = S.empty(),
                this.viewProjectionMatrix = S.empty(),
                e ? this.loadView(e, !0) : (this.saveResetView(),
                    this.updateView(),
                    this.updateProjection())
        }

        function W(e, t, i, s) {
            var n;
            if (this.mobile = !!/Android|iPhone|iPod|iPad|Windows Phone|IEMobile|BlackBerry|webOS/.test(navigator.userAgent),
                this.mobileFast = !!/iPhone|iPad/.test(navigator.userAgent),
                n = !this.mobile)
                e: {
                    if ((n = document.createElement("canvas")).width = n.height = 16,
                        n = n.getContext("webgl", {}) || n.getContext("experimental-webgl", {})) {
                        var r = n.getExtension("WEBGL_debug_renderer_info");
                        if (r) {
                            n = n.getParameter(r.UNMASKED_RENDERER_WEBGL),
                                n = !!/Intel|INTEL/.test(n);
                            break e
                        }
                    }
                    n = !1
                }
            this.desktopSlow = n,
                this.domRoot = document.createElement("div"),
                this.domRoot.style.width = e + "px",
                this.domRoot.style.height = t + "px",
                this.initCanvas(e, t),
                this.scene = this.input = null,
                this.sceneURL = i,
                this.sleepCounter = 8,
                this.onLoad = null,
                this.stripData = new D(),
                this.ui = new j(this),
                this.ui.setSize(e, t),
                this.ui.showPreview(s)
        }
        H.prototype.saveResetView = function () {
                this.resetDesc = {
                    angles: [this.rotation[0], this.rotation[1]],
                    pivot: [this.pivot[0], this.pivot[1], this.pivot[2]],
                    limits: this.limits,
                    orbitRadius: this.radius,
                    fov: this.fov
                }
            },
            H.prototype.loadView = function (e, t) {
                e && (this.rotation[0] = e.angles[0],
                    this.rotation[1] = e.angles[1],
                    rotInfo.pivot[0] || (rotInfo.pivot[0] = e.pivot[0]),
                    rotInfo.pivot[1] || (rotInfo.pivot[1] = e.pivot[1]),
                    rotInfo.pivot[2] || (rotInfo.pivot[2] = e.pivot[2]),
                    this.pivot[0] = rotInfo.pivot[0],
                    this.pivot[1] = rotInfo.pivot[1],
                    this.pivot[2] = rotInfo.pivot[2],
                    this.radius = parseFloat(getQueryVariable('currentdis') ? Number(getQueryVariable('currentdis')) : e.orbitRadius),
                    this.fov = e.fov,

                    this.limits = e.limits,

                    //   this.limits = {
                    //     orbitRadius:{
                    //       max: getQueryVariable('camdismax')?Number(getQueryVariable('camdismax')): e.limits.orbitRadius.max,
                    //       min: getQueryVariable('camdismmin')?Number(getQueryVariable('camdismmin')): e.limits.orbitRadius.min,
                    //     }
                    //   },
                    t && this.saveResetView(),
                    this.updateView(),
                    this.updateProjection())
                //   console.log(e.limits,this.limits,'limits');

            },
            H.prototype.reset = function () {
                this.loadView(this.resetDesc)
            },
            H.prototype.updateView = function () {
                if (void 0 !== this.limits) {
                    if (this.limits.angles) {
                        var e = this.limits.angles.x,
                            t = this.limits.angles.y;
                        if (void 0 !== e) {
                            var i = this.rotation[0] - e.offset;
                            e = Math.min(Math.max(i, e.min), e.max);
                            this.rotation[0] += e - i
                        }
                        void 0 !== t && (i = this.rotation[1] - t.offset,
                            e = Math.min(Math.max(i, t.min), t.max),
                            this.rotation[1] += e - i)
                    }

                    void 0 !== this.limits.orbitRadius && (t = this.limits.orbitRadius.min,
                            i = this.limits.orbitRadius.max,
                            void 0 !== t && (this.radius = Math.max(this.radius, t)),
                            void 0 !== i && (this.radius = Math.min(this.radius, i))),
                        void 0 !== this.limits.pan && (t = this.limits.pan,
                            i = this.resetDesc.pivot,
                            t.x && (this.pivot[0] = i[0]),
                            t.y && (this.pivot[1] = i[1]),
                            t.z && (this.pivot[2] = i[2]))
                }
                S.translation(this.transform, 0, 0, this.radius),
                    t = S.rotation(S.empty(), this.rotation[0], 0),
                    i = S.rotation(S.empty(), this.rotation[1], 1),
                    S.mul(t, i, t),
                    S.mul(this.transform, t, this.transform),
                    this.transform[12] += this.pivot[0],
                    this.transform[13] += this.pivot[1],
                    this.transform[14] += this.pivot[2],
                    S.invert(this.viewMatrix, this.transform),
                    S.mul(this.viewProjectionMatrix, this.viewMatrix, this.projectionMatrix)
            },
            H.prototype.updateProjection = function (e) {
                S.perspectiveInfinite(this.projectionMatrix, this.fov, this.size[0] / this.size[1], this.nearPlane, e),
                    S.mul(this.viewProjectionMatrix, this.projectionMatrix, this.viewMatrix)
            },
            W.prototype.initCanvas = function (e, t) {
                if (this.canvas && this.canvas.parentNode && this.canvas.parentNode.removeChild(this.canvas),
                    this.canvas = document.createElement("canvas"),
                    this.pixelRatio = window.devicePixelRatio || 1,
                    this.mobile) {
                    var i = this.mobileFast ? 1.5 : 1;
                    this.pixelRatio = this.pixelRatio > i ? i : this.pixelRatio
                } else
                    this.desktopSlow && (this.pixelRatio = 1);
                this.canvas.width = e * this.pixelRatio,
                    this.canvas.height = t * this.pixelRatio,
                    this.canvas.style.width = e + "px",
                    this.canvas.style.height = t + "px",
                    this.canvas.style.position = "absolute",
                    this.domRoot.appendChild(this.canvas)
            },
            W.prototype.initGL = function () {
                var e = {
                    alpha: !!I.transparentBackground,
                    depth: !1,
                    stencil: !1,
                    antialias: !1,
                    premultipliedAlpha: !!I.transparentBackground,
                    preserveDrawingBuffer: !1
                };
                e = this.gl = this.canvas.getContext("webgl", e) || this.canvas.getContext("experimental-webgl", e);
                return this.gl ? (this.canvas.addEventListener("webglcontextlost", function (e) {
                        e.preventDefault()
                    }, !1),
                    this.canvas.addEventListener("webglcontextrestored", function (e) {
                            this.loadScene(this.sceneURL)
                        }
                        .bind(this), !1),
                    e.ext = {
                        textureAniso: e.getExtension("EXT_texture_filter_anisotropic") || e.getExtension("WEBKIT_EXT_texture_filter_anisotropic") || e.getExtension("MOZ_EXT_texture_filter_anisotropic"),
                        textureFloat: e.getExtension("OES_texture_float"),
                        textureFloatLinear: e.getExtension("OES_texture_float_linear"),
                        textureHalf: e.getExtension("OES_texture_half_float"),
                        textureHalfLinear: e.getExtension("OES_texture_half_float_linear"),
                        textureDepth: e.getExtension("WEBGL_depth_texture"),
                        colorBufferFloat: e.getExtension("WEBGL_color_buffer_float"),
                        colorBufferHalf: e.getExtension("EXT_color_buffer_half_float"),
                        index32bit: e.getExtension("OES_element_index_uint"),
                        loseContext: e.getExtension("WEBGL_lose_context"),
                        derivatives: e.getExtension("OES_standard_derivatives"),
                        renderInfo: e.getExtension("WEBGL_debug_renderer_info")
                    },
                    e.limits = {
                        textureSize: e.getParameter(e.MAX_TEXTURE_SIZE),
                        textureCount: e.getParameter(e.MAX_TEXTURE_IMAGE_UNITS),
                        varyings: e.getParameter(e.MAX_VARYING_VECTORS),
                        vertexAttribs: e.getParameter(e.MAX_VERTEX_ATTRIBS),
                        vertexUniforms: e.getParameter(e.MAX_VERTEX_UNIFORM_VECTORS),
                        fragmentUniforms: e.getParameter(e.MAX_FRAGMENT_UNIFORM_VECTORS),
                        viewportSizes: e.getParameter(e.MAX_VIEWPORT_DIMS),
                        vendor: e.getParameter(e.VENDOR),
                        version: e.getParameter(e.VERSION)
                    },
                    e.hints = {
                        mobile: this.mobile,
                        pixelRatio: this.pixelRatio
                    },
                    e.enable(e.DEPTH_TEST),
                    e.shaderCache = new O(e),
                    e.textureCache = new N(e),
                    this.allocBacking(),
                    !0) : (this.ui.showFailure('webgl出错。</br>建议您将浏览器升级至最新版本，以获最好的体验。<br><span style="font-size:0.8em">获知更多webgl浏览器信息请<a href="webglInfo.html" style="color: #a6ccea;">点击此处</a></span>', this),
                    !1)
            },
            W.prototype.allocBacking = function () {
                var e = this.gl,
                    t = !1,
                    i = {
                        width: this.canvas.width,
                        height: this.canvas.height
                    };
                for (this.mainColor = new U(e, i),
                    this.mainDepth = null,
                    e.ext.textureDepth && (this.mainDepth = new U(e, {
                            width: this.canvas.width,
                            height: this.canvas.height,
                            nofilter: !0
                        }),
                        this.mainDepth.loadArray(null, e.DEPTH_COMPONENT, e.UNSIGNED_INT)),
                    e.ext.textureHalf && e.ext.textureHalfLinear && (this.mainColor.loadArray(null, e.RGBA, e.ext.textureHalf.HALF_FLOAT_OES),
                        this.mainBuffer = new m(e, {
                            color0: this.mainColor,
                            depth: this.mainDepth,
                            createDepth: !this.mainDepth
                        }),
                        t = this.mainBuffer.valid),
                    !t && e.ext.textureFloat && e.ext.textureFloatLinear && !e.hints.mobile && (this.mainColor.loadArray(null, e.RGBA, e.FLOAT),
                        this.mainBuffer = new m(e, {
                            color0: this.mainColor,
                            depth: this.mainDepth,
                            createDepth: !this.mainDepth
                        }),
                        t = this.mainBuffer.valid); !t;)
                    this.mainColor = new U(e, i),
                    this.mainColor.loadArray(null, e.RGBA, e.UNSIGNED_BYTE),
                    this.mainBuffer = new m(e, {
                        color0: this.mainColor,
                        depth: this.mainDepth,
                        createDepth: !this.mainDepth
                    }),
                    t = this.mainBuffer.valid,
                    i.width /= 2,
                    i.height /= 2,
                    this.mainDepth && (this.mainDepth.destroy(),
                        this.mainDepth = null);
                this.mainBufferNoDepth = new m(e, {
                    color0: this.mainColor
                })
            },
            W.prototype.loadScene = function (e) {
                if (this.sceneURL = e || this.sceneURL,
                    this.scene = this.input = null,
                    this.initGL() && this.sceneURL) {
                    var t = this.ui.signalLoadProgress.bind(this.ui);
                    e = function (e) {
                            t(1, 1),
                                this.scene = new k(this.gl),
                                this.scene.stripData = this.stripData,
                                this.scene.load(new h(e)) ? this.scene.metaData.tbVersion <= 2070 ? this.ui.showFailure("模型文件版本过低", this) : (this.bindInput(),
                                    this.requestFrame(this.updateLoad.bind(this)),
                                    this.onLoad && this.onLoad()) : this.ui.showFailure("模型文件无法读取或无效", this)
                        }
                        .bind(this);
                    var i = function () {
                            this.ui.showFailure("模型文件 (" + this.sceneURL + ") 无法获取.", this)
                        }
                        .bind(this);
                    C.fetchBinary(this.sceneURL, e, i, t)
                }
            },
            W.prototype.unload = function () {
                delete this.scene,
                    delete this.input,
                    delete this.ui,
                    delete this.mainColor,
                    delete this.mainBuffer,
                    delete this.gl;
                var e = this.domRoot.clientWidth,
                    t = this.domRoot.clientHeight;
                this.initCanvas(e, t),
                    this.ui = new j(this),
                    this.ui.setSize(e, t),
                    this.ui.showPreview(),
                    this.cancelFrame()
            },
            W.prototype.bindInput = function () {
                this.input = new e(this.ui.container),
                    this.input.onDrag.push(function (e, t, i, s) {
                            e = 1 - 2.2 / (Math.sqrt(i * i + s * s) + 2.2),
                                (t = this.scene.view).rotation[1] -= .4 * i * e,
                                t.rotation[0] -= .4 * s * e,
                                t.rotation[0] = 90 < t.rotation[0] ? 90 : t.rotation[0],
                                t.rotation[0] = t.rotation[0] < -90 ? -90 : t.rotation[0],
                                t.updateView(),
                                this.wake()
                        }
                        .bind(this)),
                    this.input.onPan.push(function (e, t) {
                            var i = this.scene.view,
                                s = -e * (n = i.fov / 45 * .8 * (i.radius / this.domRoot.clientHeight)),
                                n = t * n;
                            i.pivot[0] += s * i.transform[0] + n * i.transform[4],
                                i.pivot[1] += s * i.transform[1] + n * i.transform[5],
                                i.pivot[2] += s * i.transform[2] + n * i.transform[6],
                                i.updateView(),
                                this.wake()
                        }
                        .bind(this)),
                    this.input.onPan2.push(function (e, t) {
                            var i = 1 - 2.2 / (Math.sqrt(e * e + t * t) + 2.2);
                            this.scene.lights.rotation -= .4 * e * i,
                                this.wake()
                        }
                        .bind(this)),
                    this.input.onZoom.push(function (e) {
                            rotInfo.stopWhenZoom && webview.stopRotate();
                            var t = this.scene.view;
                            t.radius *= 1 - .002 * e,
                                t.radius = t.radius < .001 ? .001 : t.radius,
                                t.radius = 1e3 < t.radius ? 1e3 : t.radius,
                                t.updateView(),
                                this.wake()
                        }
                        .bind(this)),
                    this.input.onDoubleTap.push(function (e, t) {
                            this.scene.view.reset(),
                                this.scene.sceneAnimator && this.scene.sceneAnimator.resetCustomView(),
                                this.wake()
                        }
                        .bind(this)),
                    this.ui.bindInput(this.input)
            },
            W.prototype.rotateWhenIdle = function () {


                // 加载完成 才需要 外部调用
                if (!window.modelLoding) return

                if (webview.rotate) return
                rotInfo.radiusK && (webview.scene.view.radius = rotInfo.radiusK / (dom.id("fdageUI").clientWidth / dom.id("fdageUI").clientHeight)),
                    webview.scene.view.pivot = rotInfo.pivot.slice(),
                    webview.rotate = setInterval(function () {
                        webview.scene.view.rotation[1] -= rotInfo.speed,
                            webview.updateView(!0, !0, 1)
                    }, 16)
            },
            W.prototype.stopRotate = function (ifFinish) { //ifFinish是否不再自动旋转

                // 加载完成 才需要 外部调用
                if (!window.modelLoding) return

                if (webview.rotate) {
                    clearInterval(webview.rotate),
                        //   console.log("clearInterval(webview.rotate)"),
                        webview.rotate = null,
                        ifFinish || (webview.countIdelTime = setTimeout(webview.rotateWhenIdle, rotInfo.idleTime))
                } else {
                    if (webview.countIdelTime) {
                        clearTimeout(webview.countIdelTime),
                            //   console.log("clearInterval(countIdelTime)"),
                            ifFinish || (webview.countIdelTime = setTimeout(webview.rotateWhenIdle, rotInfo.idleTime))
                    }
                }
            },

            W.prototype.resetView = function (e) { //add
                if (window.modelLoding) {

                    this.scene.view.reset()
                    this.wake()
                }
            },
            W.prototype.zoomIn = function () { //add 放大
                if (window.modelLoding) this.input.onZoom[0](130); //放大会比缩小快一些，所以降低数值

            }

        W.prototype.zoomOut = function () { //add 缩小
            if (window.modelLoding) this.input.onZoom[0](-150);

        }



        W.prototype.wake = function (e) {
                e = e || 16,
                    this.sleepCounter = this.sleepCounter < e ? e : this.sleepCounter,
                    this.scene.postRender.discardAAHistory(),
                    this.requestFrame(this.update.bind(this))
            },
            W.prototype.requestFrame = function (e) {
                var t = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
                if (!this.frameRequestPending) {
                    var i = function () {
                            this.frameRequestPending = 0,
                                e()
                        }
                        .bind(this);
                    this.frameRequestPending = t(i, this.canvas)
                }
            },
            W.prototype.cancelFrame = function () {
                this.frameRequestPending && (window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.webkitCancelAnimationFrame || window.msCancelAnimationFrame)(this.frameRequestPending)
            },
            W.prototype.fullscreenChange = function () {
                g.active() ? (this.oldRootWidth = this.domRoot.style.width,
                        this.oldRootHeight = this.domRoot.style.height,
                        this.domRoot.style.width = "100%",
                        this.domRoot.style.height = "100%") : (this.domRoot.style.width = this.oldRootWidth,
                        this.domRoot.style.height = this.oldRootHeight),
                    this.wake()
            },
            W.prototype.resize = function (e, t) {
                e && t ? (this.domRoot.style.width = e + "px",
                        this.domRoot.style.height = t + "px") : (e = this.domRoot.clientWidth,
                        t = this.domRoot.clientHeight),
                    this.canvas.width = e * this.pixelRatio,
                    this.canvas.height = t * this.pixelRatio,
                    this.canvas.style.width = e + "px",
                    this.canvas.style.height = t + "px",
                    this.ui.setSize(e, t),
                    this.allocBacking(),
                    this.wake()
            },
            W.prototype.updateLoad = function () {
                this.scene.complete() ? this.start() : this.requestFrame(this.updateLoad.bind(this)),
                    this.ui.animate()
            },
            W.prototype.start = function () {
                // console.log('模型加载完成');
                window.modelLoding = true
                // setTimeout(() => {
                //     let dom = document.querySelector('.bacBox')
                //     dom.style.opacity = 0
                //     dom.style.pointerEvents = 'none'
                // }, 500);

                this.scene.view.updateView(),
                    this.ui.showActiveView(),
                    this.requestFrame(this.update.bind(this)),
                    window.autoRotate && this.rotateWhenIdle(),
                    document.documentElement.style.height = "100%",
                    document.documentElement.style.width = "100%",
                    document.documentElement.style.margin = "0",
                    document.documentElement.style.padding = "0",
                    document.body.style.height = "100%",
                    document.body.style.width = "100%",
                    document.body.style.margin = "0",
                    document.body.style.padding = "0"
            },
            W.prototype.update = function () {
                var e = this.scene.sceneAnimator && !this.scene.sceneAnimator.paused;
                (0 < this.sleepCounter || this.ui.animating() || e || this.stripData.animationActive) && (this.stripData.update(),
                    this.ui.animate(),
                    this.scene.update(),
                    this.drawScene(),
                    this.requestFrame(this.update.bind(this))),
                e ? this.scene.postRender.discardAAHistory() : this.sleepCounter--
            },
            W.prototype.reDrawScene = function () {
                this.stripData.update(),
                    this.ui.animate(),
                    this.scene.update(),
                    this.drawScene(),
                    this.requestFrame(this.update.bind(this)),
                    this.scene.postRender.discardAAHistory()
            },
            W.prototype.drawScene = function () {
                this.gl.isContextLost() || (this.domRoot.clientWidth == this.canvas.clientWidth && this.domRoot.clientHeight == this.canvas.clientHeight || this.resize(),
                    this.scene.view.size = [this.mainBuffer.width, this.mainBuffer.height],
                    this.scene.view.updateProjection(),
                    this.scene.postRender.adjustProjectionForSupersampling(this.scene.view),
                    this.scene.collectShadows(this.mainBuffer),
                    this.mainBuffer.bind(),
                    this.scene.draw(this.mainBuffer),
                    this.mainDepth && (this.mainBufferNoDepth.bind(),
                        this.scene.drawSecondary(this.mainDepth)),
                    this.scene.postRender.present(this.mainColor, this.canvas.width, this.canvas.height, this.stripData.active()))
            },
            W.prototype.updateView = function (e, t, i) {
                t && webview.scene.view.updateView(),
                    webview.wake(i || 4),
                    e && webview.scene.postRender.discardAAHistory()
            },
            (I = void 0 === I ? {} : I).WebViewer = W,
            I.dataLocale = "images/";
        var G = {
            "alphaprepassfrag.glsl": "precision mediump float;\n#include <matdither.glsl>\nuniform sampler2D tAlbedo;varying mediump vec2 d;void main(){float e=texture2D(tAlbedo,d).a;if(e<=f(d.x)){discard;}gl_FragColor=vec4(0.0);}",
            "alphaprepassvert.glsl": "precision highp float;uniform mat4 uModelViewProjectionMatrix;uniform vec2 uUVOffset;attribute vec3 vPosition;attribute vec2 vTexCoord;varying mediump vec2 d;vec4 h(mat4 i,vec3 p){return i[0]*p.x+(i[1]*p.y+(i[2]*p.z+i[3]));}void main(void){gl_Position=h(uModelViewProjectionMatrix,vPosition.xyz);d=vTexCoord+uUVOffset;}",
            "bloom.glsl": "precision mediump float;uniform sampler2D tInput;uniform vec4 uKernel[BLOOM_SAMPLES];varying highp vec2 j;void main(void){vec3 c=vec3(0.0,0.0,0.0);for(int k=0;k<BLOOM_SAMPLES;++k){vec3 l=uKernel[k].xyz;vec3 m=texture2D(tInput,j+l.xy).xyz;m=max(m,vec3(0.0,0.0,0.0));c+=m*l.z;}gl_FragColor.xyz=c;gl_FragColor.w=0.0;}",
            "bloomshrink.glsl": "precision highp float;uniform sampler2D tInput;varying highp vec2 j;void main(void){float o=0.25/256.0;gl_FragColor=0.25*(texture2D(tInput,j+vec2(o,o))+texture2D(tInput,j+vec2(o,-o))+texture2D(tInput,j+vec2(-o,o))+texture2D(tInput,j+vec2(-o,-o)));}",
            "fogfrag.glsl": "precision highp float;uniform sampler2D tDepth;uniform vec3 uDepthToZ;uniform vec4 uUnproject;uniform mat4 uInvViewMatrix;uniform float uFogInvDistance;uniform float uFogOpacity;uniform float uFogDispersion;uniform vec3 uFogType;uniform vec3 uFogColor;uniform float uFogIllum;uniform mat4 uLightMatrix;\n#ifdef FOG_IBL\nuniform vec4 uFogLightSphere[9];\n#else\nuniform vec4 uSpotParams;uniform vec4 uLightPosition;uniform vec3 uLightColor;uniform vec4 uLightAttenuation;\n#ifdef FOG_SHADOWS\nuniform mat4 uShadowProj;uniform sampler2D uShadowMap;uniform float uDitherOffset;uniform vec4 uCylinder;\n#endif\n#endif\nvec4 h(mat4 i,vec3 p){return i[0]*p.x+(i[1]*p.y+(i[2]*p.z+i[3]));}vec3 u(mat4 i,vec3 v){return i[0].xyz*v.x+i[1].xyz*v.y+i[2].xyz*v.z;}float A(float B){B*=uFogInvDistance;float C=uFogType.x*min(B,1.0)+(uFogType.y-uFogType.y/(1.0+16.0*B*B))+(uFogType.z-uFogType.z*exp(-3.0*B));return C*uFogOpacity;}\n#ifdef FOG_SHADOWS\nfloat D(vec3 E){vec4 p=h(uShadowProj,E);vec3 F=p.xyz/p.w;vec4 G=texture2D(uShadowMap,F.xy);float H=(G.x+G.y*(1.0/255.0))+G.z*(1.0/65025.0);return F.z<H || H>=1.0?1.0:0.0;}float f(vec2 I){return fract(sin(dot(I,vec2(12.9898,78.233)))*43758.5453+uDitherOffset);}void J(vec3 K,vec3 L,out float M,out float N){vec3 v=uSpotParams.xyz,p=uCylinder.xyz;vec3 O=L-dot(L,v)*v;vec3 P=(K-p)-dot(K-p,v)*v;float a=dot(O,O);float b=2.0*dot(O,P);float c=dot(P,P)-uCylinder.w;float Q=b*b-4.0*a*c;if(Q>=0.0){Q=sqrt(Q);M=(-b-Q)/(2.0*a);N=(-b+Q)/(2.0*a);}else {M=N=0.0;}}\n#endif\nvarying vec2 j;void main(void){vec3 R=uInvViewMatrix[3].xyz;float H=texture2D(tDepth,j).x;H=min(H,0.9999);vec3 S;S.z=uDepthToZ.y/(uDepthToZ.z*H+uDepthToZ.x);S.xy=S.z*(j*uUnproject.xy+uUnproject.zw);S=h(uInvViewMatrix,S).xyz;vec3 T;T.xy=(j*uUnproject.xy+uUnproject.zw);T.z=1.0;T=normalize(u(uInvViewMatrix,-T).xyz);vec3 U=uFogColor;\n#if defined(FOG_IBL)\nvec3 G=u(uLightMatrix,T);vec3 V=uFogLightSphere[0].xyz;V+=uFogLightSphere[1].xyz*G.y;V+=uFogLightSphere[2].xyz*G.z;V+=uFogLightSphere[3].xyz*G.x;vec3 swz=G.yyz*G.xzx;V+=uFogLightSphere[4].xyz*swz.x;V+=uFogLightSphere[5].xyz*swz.y;V+=uFogLightSphere[7].xyz*swz.z;vec3 sqr=G*G;V+=uFogLightSphere[6].xyz*(3.0*sqr.z-1.0);V+=uFogLightSphere[8].xyz*(sqr.x-sqr.y);U=mix(U,U*V,uFogIllum);float C=A(length(S-R));gl_FragColor.xyz=U*C;gl_FragColor.w=C;return;\n#else\n#if defined(FOG_SPOT) || defined(FOG_OMNI)\nfloat W=0.0,X=0.0;{float r=1.0/(uLightAttenuation.z);float a=1.0;float b=2.0*dot(T,R-uLightPosition.xyz);float c=dot(uLightPosition.xyz,uLightPosition.xyz)+dot(R,R)+-2.0*dot(uLightPosition.xyz,R)+-r*r;float Q=b*b-4.0*a*c;if(Q>=0.0){Q=sqrt(Q);W=(-b-Q)/(2.0*a);X=(-b+Q)/(2.0*a);}}\n#if defined(FOG_SPOT)\n{float Y=uSpotParams.w,Z=1.0-Y;vec3 v=T;vec3 dc=uSpotParams.xyz;vec3 dd=R-uLightPosition.xyz;vec3 de=v-dot(v,dc)*dc,df=dd-dot(dd,dc)*dc;float a=Y*dot(de,de)-Z*dot(v,dc)*dot(v,dc);float b=2.0*Y*dot(de,df)-2.0*Z*dot(v,dc)*dot(dd,dc);float c=Y*dot(df,df)-Z*dot(dd,dc)*dot(dd,dc);float Q=b*b-4.0*a*c;if(Q>=0.0){float dh=(-b-sqrt(Q))/(2.0*a);float di=(-b+sqrt(Q))/(2.0*a);if(di<dh){float de=dh;dh=di;di=de;}bool dj=dot(-uLightPosition.xyz+R+T*dh,uSpotParams.xyz)<=0.0;bool dk=dot(-uLightPosition.xyz+R+T*di,uSpotParams.xyz)<=0.0;if(!dj ||!dk){if(dj){dh=di;di=X;}else if(dk){di=dh;dh=W;}W=max(W,dh);X=min(X,di);}else {X=W=0.0;}}else {X=W=0.0;}}\n#endif\nfloat tx=dot(T,S-R);W=clamp(W,0.0,tx);X=clamp(X,0.0,tx);float dl=0.0;if(X>W){\n#ifdef FOG_SHADOWS\n#ifdef MOBILE\n#define SAMPLES 16\n#else\n#define SAMPLES 32\n#endif\nfloat dm=f(j)*(X-W)/float(SAMPLES-2);\n#else\n#define SAMPLES 8\nfloat dm=0.0;\n#endif\nfor(int k=0;k<SAMPLES;++k){float t=W+(X-W)*float(k)/float(SAMPLES-1);vec3 p=R+(t+dm)*T;float a=clamp(length(p-uLightPosition.xyz)*uLightAttenuation.z,0.0,1.0);a=1.0+uLightAttenuation.x*a+uLightAttenuation.y*a*a;\n#ifdef FOG_SHADOWS\na*=D(p);\n#endif\ndl+=a-a*A(t);}dl*=1.0/float(SAMPLES);dl*=(X-W)*uLightAttenuation.z;dl*=A(X-W);}U*=dl*uFogIllum;\n#elif defined(FOG_DIR)\nfloat C=A(dot(T,S-R));\n#ifdef FOG_SHADOWS\nfloat W,X;J(R,T,W,X);float tx=dot(T,S-R);W=clamp(W,0.0,tx);X=clamp(X,0.0,tx);if(X>W){\n#ifdef MOBILE\n#define SAMPLES 16\n#else\n#define SAMPLES 32\n#endif\nfloat dl=0.0;float dm=f(j)*(X-W)/float(SAMPLES-2);float dn=(X-W)*(1.0/float(SAMPLES));for(int k=0;k<SAMPLES;++k){float t=W+float(k)*dn+dm;vec3 p=R+t*T;float s=D(p);C-=(1.0-s)*(A(t+dn)-A(t));}}\n#endif\nfloat du=0.5+0.5*dot(T,-uSpotParams.xyz);du=1.0+uFogDispersion*(2.0*du*du-1.0);U*=(0.1*C)*(du*uFogIllum);\n#endif\ngl_FragColor.xyz=U*uLightColor;gl_FragColor.w=0.0;\n#endif\n}",
            "fogvert.glsl": "precision highp float;attribute vec2 vCoord;varying vec2 j;void main(void){j=vCoord;gl_Position.xy=2.0*vCoord-vec2(1.0,1.0);gl_Position.zw=vec2(0.0,1.0);}",
            "matdither.glsl": "float f(highp float I){highp float G=0.5*fract(gl_FragCoord.x*0.5)+0.5*fract(gl_FragCoord.y*0.5);return 0.4+0.6*fract(G+3.141592e6*I);}",
            "matfrag.glsl": "\n#extension GL_OES_standard_derivatives : enable\nprecision mediump float;varying highp vec3 dv;varying mediump vec2 d;varying mediump vec3 dA;varying mediump vec3 dB;varying mediump vec3 dC;\n#ifdef VERTEX_COLOR\nvarying lowp vec4 dD;\n#endif\n#ifdef TEXCOORD_SECONDARY\nvarying mediump vec2 dE;\n#endif\nuniform sampler2D tAlbedo;uniform sampler2D tReflectivity;uniform sampler2D tNormal;uniform sampler2D tExtras;uniform sampler2D tSkySpecular;\n#ifdef REFRACTION\nuniform sampler2D tRefraction;\n#endif\nuniform vec4 uDiffuseCoefficients[9];uniform vec3 uCameraPosition;uniform float uAlphaTest;uniform vec3 uFresnel;uniform float uHorizonOcclude;uniform float uHorizonSmoothing;\n#ifdef EMISSIVE\nuniform float uEmissiveScale;uniform vec4 uTexRangeEmissive;\n#endif\n#ifdef AMBIENT_OCCLUSION\nuniform vec4 uTexRangeAO;\n#endif\n#ifdef REFRACTION\nuniform float uRefractionIOREntry;uniform float uRefractionRayDistance;uniform vec3 uRefractionTint;uniform float uRefractionAlbedoTint;uniform mat4 uRefractionViewProjection;uniform vec4 uTexRangeRefraction;\n#endif\n#ifdef LIGHT_COUNT\nuniform vec4 uLightPositions[LIGHT_COUNT];uniform vec3 uLightDirections[LIGHT_COUNT];uniform vec3 uLightColors[LIGHT_COUNT];uniform vec3 uLightParams[LIGHT_COUNT];uniform vec3 uLightSpot[LIGHT_COUNT];\n#endif\n#ifdef ANISO\nuniform float uAnisoStrength;uniform vec3 uAnisoTangent;uniform float uAnisoIntegral;uniform vec4 uTexRangeAniso;\n#endif\n#define saturate(x) clamp( x, 0.0, 1.0 )\n#include <matsampling.glsl>\n#include <matlighting.glsl>\n#include <matshadows.glsl>\n#include <matskin.glsl>\n#include <matmicrofiber.glsl>\n#include <matstrips.glsl>\n#ifdef TRANSPARENCY_DITHER\n#include <matdither.glsl>\n#endif\nvoid main(void){vec4 m=texture2D(tAlbedo,d);vec3 dF=dG(m.xyz);float e=m.w;\n#ifdef VERTEX_COLOR\n{vec3 dH=dD.xyz;\n#ifdef VERTEX_COLOR_SRGB\ndH=dH*(dH*(dH*0.305306011+vec3(0.682171111))+vec3(0.012522878));\n#endif\ndF*=dH;\n#ifdef VERTEX_COLOR_ALPHA\ne*=dD.w;\n#endif\n}\n#endif\n#ifdef ALPHA_TEST\nif(e<uAlphaTest){discard;}\n#endif\n#ifdef TRANSPARENCY_DITHER\ne=(e>f(d.x))?1.0:e;\n#endif\nvec3 dI=dJ(texture2D(tNormal,d).xyz);\n#ifdef ANISO\n#ifdef ANISO_NO_DIR_TEX\nvec3 dK=dL(uAnisoTangent);\n#else\nm=dM(d,uTexRangeAniso);vec3 dK=2.0*m.xyz-vec3(1.0);dK=dL(dK);\n#endif\ndK=dK-dI*dot(dK,dI);dK=normalize(dK);vec3 dN=dK*uAnisoStrength;\n#endif\nvec3 dO=normalize(uCameraPosition-dv);m=texture2D(tReflectivity,d);vec3 dP=dG(m.xyz);float dQ=m.w;float dR=dQ;\n#ifdef HORIZON_SMOOTHING\nfloat dS=dot(dO,dI);dS=uHorizonSmoothing-dS*uHorizonSmoothing;dQ=mix(dQ,1.0,dS*dS);\n#endif\n#ifdef STRIPVIEW\ndT dU;dV(dU,dQ,dP);\n#endif\nfloat dW=1.0;\n#ifdef AMBIENT_OCCLUSION\n#ifdef AMBIENT_OCCLUSION_SECONDARY_UV\ndW=dM(dE,uTexRangeAO).x;\n#else\ndW=dM(d,uTexRangeAO).x;\n#endif\ndW*=dW;\n#endif\n#if defined(SKIN)\ndX dY;dZ(dY);dY.ec*=dW;\n#elif defined(MICROFIBER)\ned ee;ef(ee,dI);ee.eh*=dW;\n#else\nvec3 ei=ej(dI);ei*=dW;\n#endif\nvec3 ek=reflect(-dO,dI);\n#ifdef ANISO\nvec3 rt=ek-(0.5*dN*dot(ek,dK));vec3 el=em(rt,mix(dQ,0.5*dQ,uAnisoStrength));\n#else\nvec3 el=em(ek,dQ);\n#endif\nel*=en(ek,dC);\n#ifdef LIGHT_COUNT\nhighp float eo=10.0/log2(dQ*0.968+0.03);eo*=eo;float eu=eo*(1.0/(8.0*3.1415926))+(4.0/(8.0*3.1415926));eu=min(eu,1.0e3);\n#ifdef SHADOW_COUNT\nev eA;\n#ifdef SKIN\n#ifdef SKIN_VERSION_1\neB(eA,SHADOW_KERNEL+SHADOW_KERNEL*dY.eC);\n#else\neD eE;float eF=SHADOW_KERNEL+SHADOW_KERNEL*dY.eC;eG(eE,eF);eB(eA,eF);\n#endif\n#else\neB(eA,SHADOW_KERNEL);\n#endif\n#endif\n#ifdef ANISO\neu*=uAnisoIntegral;\n#endif\nfor(int k=0;k<LIGHT_COUNT;++k){vec3 eH=uLightPositions[k].xyz-dv*uLightPositions[k].w;float eI=inversesqrt(dot(eH,eH));eH*=eI;float a=saturate(uLightParams[k].z/eI);a=1.0+a*(uLightParams[k].x+uLightParams[k].y*a);float s=saturate(dot(eH,uLightDirections[k]));s=saturate(uLightSpot[k].y-uLightSpot[k].z*(1.0-s*s));vec3 eJ=(a*s)*uLightColors[k].xyz;\n#if defined(SKIN)\n#ifdef SHADOW_COUNT\n#ifdef SKIN_VERSION_1\neK(dY,eA.eL[k],1.0,eH,dI,eJ);\n#else\neK(dY,eA.eL[k],eE.eE[k],eH,dI,eJ);\n#endif\n#else\neK(dY,1.0,0.0,eH,dI,eJ);\n#endif\n#elif defined(MICROFIBER)\n#ifdef SHADOW_COUNT\neM(ee,eA.eL[k],eH,dI,eJ);\n#else\neM(ee,1.0,eH,dI,eJ);\n#endif\n#else\nfloat eN=saturate((1.0/3.1415926)*dot(eH,dI));\n#ifdef SHADOW_COUNT\neN*=eA.eL[k];\n#endif\nei+=eN*eJ;\n#endif\nvec3 eO=eH+dO;\n#ifdef ANISO\neO=eO-(dN*dot(eO,dK));\n#endif\neO=normalize(eO);float eP=eu*pow(saturate(dot(eO,dI)),eo);\n#ifdef SHADOW_COUNT\neP*=eA.eL[k];\n#endif\nel+=eP*eJ;}\n#endif\n#if defined(SKIN)\nvec3 ei,diff_extra;eQ(ei,diff_extra,dY,dO,dI,dQ);\n#elif defined(MICROFIBER)\nvec3 ei,diff_extra;eR(ei,diff_extra,ee,dO,dI,dQ);\n#endif\nvec3 eS=eT(dO,dI,dP,dQ*dQ);el*=eS;\n#ifdef REFRACTION\nvec4 eU;{vec3 G=refract(-dO,dI,uRefractionIOREntry);G=dv+G*uRefractionRayDistance;vec4 eV=uRefractionViewProjection[0]*G.x+(uRefractionViewProjection[1]*G.y+(uRefractionViewProjection[2]*G.z+uRefractionViewProjection[3]));vec2 c=eV.xy/eV.w;c=0.5*c+vec2(0.5,0.5);vec2 i=mod(floor(c),2.0);c=fract(c);c.x=i.x>0.0?1.0-c.x:c.x;c.y=i.y>0.0?1.0-c.y:c.y;eU.rgb=texture2D(tRefraction,c).xyz;eU.rgb=mix(eU.rgb,eU.rgb*dF,uRefractionAlbedoTint);eU.rgb=eU.rgb-eU.rgb*eS;eU.rgb*=uRefractionTint;\n#ifdef REFRACTION_NO_MASK_TEX\neU.a=1.0;\n#else\neU.a=dM(d,uTexRangeRefraction).x;\n#endif\n}\n#endif\n#ifdef DIFFUSE_UNLIT\ngl_FragColor.xyz=dF;\n#else\ngl_FragColor.xyz=ei*dF;\n#endif\n#ifdef REFRACTION\ngl_FragColor.xyz=mix(gl_FragColor.xyz,eU.rgb,eU.a);\n#endif\ngl_FragColor.xyz+=el;\n#if defined(SKIN) || defined(MICROFIBER)\ngl_FragColor.xyz+=diff_extra;\n#endif\n#ifdef EMISSIVE\n#ifdef EMISSIVE_SECONDARY_UV\nvec2 eW=dE;\n#else\nvec2 eW=d;\n#endif\ngl_FragColor.xyz+=uEmissiveScale*dG(dM(eW,uTexRangeEmissive).xyz);\n#endif\n#ifdef STRIPVIEW\ngl_FragColor.xyz=eX(dU,dI,dF,dP,dR,ei,el,gl_FragColor.xyz);\n#endif\n#ifdef NOBLEND\ngl_FragColor.w=1.0;\n#else\ngl_FragColor.w=e;\n#endif\n}",
            "matlighting.glsl": "vec3 eY(vec3 eZ,float fc){return exp(-0.5*fc/(eZ*eZ))/(eZ*2.5066283);}vec3 fd(vec3 eZ){return vec3(1.0,1.0,1.0)/(eZ*2.5066283);}vec3 fe(vec3 ff){return vec3(-0.5,-0.5,-0.5)/(ff);}vec3 fh(vec3 fi,float fc){return exp(fi*fc);}\n#define SAMPLE_COUNT 21.0\n#define SAMPLE_HALF 10.0\n#define GAUSS_SPREAD 0.05\nvec3 fj(float fk,float fl,vec3 fm){vec3 fn=vec3(fl,fl,fl);fn=0.8*fn+vec3(0.2);vec3 fo=cos(fn*3.14159);vec3 fu=cos(fn*3.14159*0.5);fu*=fu;fu*=fu;fu*=fu;fn=fn+0.05*fo*fu*fm;fu*=fu;fu*=fu;fu*=fu;fn=fn+0.1*fo*fu*fm;fn=saturate(fn);fn*=fn*1.2;return fn;}vec3 fv(vec3 fm){return vec3(1.0,1.0,1.0)/3.1415926;}float fA(float fk,float fm){return saturate(-fk*fm+fk+fm);}vec3 fB(float fk,vec3 fm){return saturate(-fk*fm+vec3(fk)+fm);}float fC(float fm){return-0.31830988618379*fm+0.31830988618379;}vec3 fD(vec3 fm){return-0.31830988618379*fm+vec3(0.31830988618379);}vec3 eT(vec3 dO,vec3 dI,vec3 dP,float fE){float C=1.0-saturate(dot(dO,dI));float fF=C*C;C*=fF*fF;C*=fE;return(dP-C*dP)+C*uFresnel;}vec2 fG(vec2 fH,vec2 fm){fH=1.0-fH;vec2 fI=fH*fH;fI*=fI;fH=mix(fI,fH*0.4,fm);return fH;}vec3 ej(vec3 fJ){\n#define c(n) uDiffuseCoefficients[n].xyz\nvec3 G=(c(0)+fJ.y*((c(1)+c(4)*fJ.x)+c(5)*fJ.z))+fJ.x*(c(3)+c(7)*fJ.z)+c(2)*fJ.z;\n#undef c\nvec3 sqr=fJ*fJ;G+=uDiffuseCoefficients[6].xyz*(3.0*sqr.z-1.0);G+=uDiffuseCoefficients[8].xyz*(sqr.x-sqr.y);return G;}void fK(inout vec3 fL,inout vec3 fM,inout vec3 fN,vec3 fJ){fL=uDiffuseCoefficients[0].xyz;fM=uDiffuseCoefficients[1].xyz*fJ.y;fM+=uDiffuseCoefficients[2].xyz*fJ.z;fM+=uDiffuseCoefficients[3].xyz*fJ.x;vec3 swz=fJ.yyz*fJ.xzx;fN=uDiffuseCoefficients[4].xyz*swz.x;fN+=uDiffuseCoefficients[5].xyz*swz.y;fN+=uDiffuseCoefficients[7].xyz*swz.z;vec3 sqr=fJ*fJ;fN+=uDiffuseCoefficients[6].xyz*(3.0*sqr.z-1.0);fN+=uDiffuseCoefficients[8].xyz*(sqr.x-sqr.y);}vec3 fO(vec3 fL,vec3 fM,vec3 fN,vec3 fP,float fm){fP=mix(vec3(1.0),fP,fm);return(fL+fM*fP.x)+fN*fP.z;}vec3 fQ(vec3 fL,vec3 fM,vec3 fN,vec3 fP,vec3 fR){vec3 fS=mix(vec3(1.0),fP.yyy,fR);vec3 fT=mix(vec3(1.0),fP.zzz,fR);return(fL+fM*fS)+fN*fT;}vec3 em(vec3 fJ,float dQ){fJ/=dot(vec3(1.0),abs(fJ));vec2 fU=abs(fJ.zx)-vec2(1.0,1.0);vec2 fV=vec2(fJ.x<0.0?fU.x:-fU.x,fJ.z<0.0?fU.y:-fU.y);vec2 fW=(fJ.y<0.0)?fV:fJ.xz;fW=vec2(0.5*(254.0/256.0),0.125*0.5*(254.0/256.0))*fW+vec2(0.5,0.125*0.5);float fX=fract(7.0*dQ);fW.y+=0.125*(7.0*dQ-fX);vec2 fY=fW+vec2(0.0,0.125);vec4 fZ=mix(texture2D(tSkySpecular,fW),texture2D(tSkySpecular,fY),fX);vec3 r=fZ.xyz*(7.0*fZ.w);return r*r;}float en(vec3 fJ,vec3 hc){float hd=dot(fJ,hc);hd=saturate(1.0+uHorizonOcclude*hd);return hd*hd;}",
            "matmicrofiber.glsl": "\n#ifdef MICROFIBER\nuniform vec4 uTexRangeFuzz;uniform vec4 uFresnelColor;uniform float uFresnelIntegral;uniform float uFresnelOcc;uniform float uFresnelGlossMask;struct ed{vec3 eh;vec3 eN;vec3 he;vec3 hf;vec3 hh;};void ef(out ed s,vec3 dI){s.eh=s.eN=ej(dI);s.he=vec3(0.0);s.hf=uFresnelColor.rgb;s.hh=uFresnelColor.aaa*vec3(1.0,0.5,0.25);\n#ifndef MICROFIBER_NO_FUZZ_TEX\nvec4 m=dM(d,uTexRangeFuzz);s.hf*=dG(m.rgb);\n#endif\n}void eM(inout ed s,float hi,vec3 eH,vec3 dI,vec3 eJ){float fk=dot(eH,dI);float eN=saturate((1.0/3.1415926)*fk);float hj=fA(fk,s.hh.z);\n#ifdef SHADOW_COUNT\neN*=hi;float hk=mix(1.0,hi,uFresnelOcc);float he=hj*hk;\n#else \nfloat he=hj;\n#endif\ns.he=he*eJ+s.he;s.eN=eN*eJ+s.eN;}void eR(out vec3 ei,out vec3 diff_extra,inout ed s,vec3 dO,vec3 dI,float dQ){s.he*=uFresnelIntegral;float fH=dot(dO,dI);vec2 hl=fG(vec2(fH,fH),s.hh.xy);s.he=s.eh*hl.x+(s.he*hl.y);s.he*=s.hf;float hm=saturate(1.0+-uFresnelGlossMask*dQ);s.he*=hm*hm;ei=s.eN;diff_extra=s.he;}\n#endif\n",
            "matsampling.glsl": "vec3 dG(vec3 c){return c*c;}vec3 dJ(vec3 n){vec3 hn=dA;vec3 ho=dB;vec3 hu=gl_FrontFacing?dC:-dC;\n#ifdef TSPACE_RENORMALIZE\nhu=normalize(hu);\n#endif\n#ifdef TSPACE_ORTHOGONALIZE\nhn-=dot(hn,hu)*hu;\n#endif\n#ifdef TSPACE_RENORMALIZE\nhn=normalize(hn);\n#endif\n#ifdef TSPACE_ORTHOGONALIZE\nho=(ho-dot(ho,hu)*hu)-dot(ho,hn)*hn;\n#endif\n#ifdef TSPACE_RENORMALIZE\nho=normalize(ho);\n#endif\n#ifdef TSPACE_COMPUTE_BITANGENT\nvec3 hv=cross(hu,hn);ho=dot(hv,ho)<0.0?-hv:hv;\n#endif\nn=2.0*n-vec3(1.0);return normalize(hn*n.x+ho*n.y+hu*n.z);}vec3 dL(vec3 t){vec3 hu=gl_FrontFacing?dC:-dC;return normalize(dA*t.x+dB*t.y+hu*t.z);}vec4 dM(vec2 hA,vec4 hB){\n#if GL_OES_standard_derivatives\nvec2 hC=fract(hA);vec2 hD=fwidth(hC);float hE=(hD.x+hD.y)>0.5?-6.0:0.0;return texture2D(tExtras,hC*hB.xy+hB.zw,hE);\n#else\nreturn texture2D(tExtras,fract(hA)*hB.xy+hB.zw);\n#endif\n}vec3 hF(sampler2D hG,vec2 hH,float hI){vec3 n=texture2D(hG,hH,hI*2.5).xyz;return dJ(n);}",
            "matshadows.glsl": "\n#ifdef SHADOW_COUNT\n#ifdef MOBILE\n#define SHADOW_KERNEL (4.0/1536.0)\n#else\n#define SHADOW_KERNEL (4.0/2048.0)\n#endif\nhighp vec4 h(highp mat4 i,highp vec3 p){return i[0]*p.x+(i[1]*p.y+(i[2]*p.z+i[3]));}uniform sampler2D tDepth0;\n#if SHADOW_COUNT > 1\nuniform sampler2D tDepth1;\n#if SHADOW_COUNT > 2\nuniform sampler2D tDepth2;\n#endif\n#endif\nuniform highp vec2 uShadowKernelRotation;uniform highp vec2 uShadowMapSize;uniform highp mat4 uShadowMatrices[SHADOW_COUNT];uniform highp vec4 uShadowTexelPadProjections[SHADOW_COUNT];\n#ifndef MOBILE\nuniform highp mat4 uInvShadowMatrices[SHADOW_COUNT];\n#endif\nhighp float hJ(highp vec3 G){\n#ifdef SHADOW_NATIVE_DEPTH\nreturn G.x;\n#else\nreturn(G.x+G.y*(1.0/255.0))+G.z*(1.0/65025.0);\n#endif\n}\n#ifndef SHADOW_COMPARE\n#define SHADOW_COMPARE(a,b) ((a) < (b) ? 1.0 : 0.0)\n#endif\n#ifndef SHADOW_CLIP\n#define SHADOW_CLIP(c,v) v\n#endif\nfloat hK(sampler2D hL,highp vec2 hA,highp float H){\n#ifndef MOBILE\nhighp vec2 c=hA*uShadowMapSize.x;highp vec2 a=floor(c)*uShadowMapSize.y,b=ceil(c)*uShadowMapSize.y;highp vec4 eE;eE.x=hJ(texture2D(hL,a).xyz);eE.y=hJ(texture2D(hL,vec2(b.x,a.y)).xyz);eE.z=hJ(texture2D(hL,vec2(a.x,b.y)).xyz);eE.w=hJ(texture2D(hL,b).xyz);highp vec4 hM;hM.x=SHADOW_COMPARE(H,eE.x);hM.y=SHADOW_COMPARE(H,eE.y);hM.z=SHADOW_COMPARE(H,eE.z);hM.w=SHADOW_COMPARE(H,eE.w);highp vec2 w=c-a*uShadowMapSize.x;vec2 s=(w.y*hM.zw+hM.xy)-w.y*hM.xy;return(w.x*s.y+s.x)-w.x*s.x;\n#else\nhighp float G=hJ(texture2D(hL,hA.xy).xyz);return SHADOW_COMPARE(H,G);\n#endif\n}highp float hN(sampler2D hL,highp vec3 hA,float hO){highp vec2 l=uShadowKernelRotation*hO;float s;s=hK(hL,hA.xy+l,hA.z);s+=hK(hL,hA.xy-l,hA.z);s+=hK(hL,hA.xy+vec2(-l.y,l.x),hA.z);s+=hK(hL,hA.xy+vec2(l.y,-l.x),hA.z);s*=0.25;return s*s;}struct ev{float eL[LIGHT_COUNT];};void eB(out ev ss,float hO){highp vec3 hP[SHADOW_COUNT];vec3 hu=gl_FrontFacing?dC:-dC;for(int k=0;k<SHADOW_COUNT;++k){vec4 hQ=uShadowTexelPadProjections[k];float hR=hQ.x*dv.x+(hQ.y*dv.y+(hQ.z*dv.z+hQ.w));\n#ifdef MOBILE\nhR*=.001+hO;\n#else\nhR*=.0005+0.5*hO;\n#endif\nhighp vec4 hS=h(uShadowMatrices[k],dv+hR*hu);hP[k]=hS.xyz/hS.w;}float m;\n#if SHADOW_COUNT > 0\nm=hN(tDepth0,hP[0],hO);ss.eL[0]=SHADOW_CLIP(hP[0].xy,m);\n#endif\n#if SHADOW_COUNT > 1\nm=hN(tDepth1,hP[1],hO);ss.eL[1]=SHADOW_CLIP(hP[1].xy,m);\n#endif\n#if SHADOW_COUNT > 2\nm=hN(tDepth2,hP[2],hO);ss.eL[2]=SHADOW_CLIP(hP[2].xy,m);\n#endif\nfor(int k=SHADOW_COUNT;k<LIGHT_COUNT;++k){ss.eL[k]=1.0;}}struct eD{highp float eE[LIGHT_COUNT];};\n#ifdef MOBILE\nvoid eG(out eD ss,float hO){for(int k=0;k<LIGHT_COUNT;++k){ss.eE[k]=1.0;}}\n#else\nhighp vec4 hT(sampler2D hL,highp vec2 hA,highp mat4 hU){highp vec4 E;E.xy=hA;\n#ifndef MOBILE\nhighp vec2 c=hA*uShadowMapSize.x;highp vec2 a=floor(c)*uShadowMapSize.y,b=ceil(c)*uShadowMapSize.y;highp vec4 hM;hM.x=hJ(texture2D(hL,a).xyz);hM.y=hJ(texture2D(hL,vec2(b.x,a.y)).xyz);hM.z=hJ(texture2D(hL,vec2(a.x,b.y)).xyz);hM.w=hJ(texture2D(hL,b).xyz);highp vec2 w=c-a*uShadowMapSize.x;vec2 s=(w.y*hM.zw+hM.xy)-w.y*hM.xy;E.z=(w.x*s.y+s.x)-w.x*s.x;\n#else \nE.z=hJ(texture2D(hL,hA.xy).xyz);\n#endif\nE=h(hU,E.xyz);E.xyz/=E.w;return E;}void eG(out eD ss,float hO){highp vec3 hV[SHADOW_COUNT];vec3 hu=gl_FrontFacing?dC:-dC;hu*=0.6;for(int k=0;k<SHADOW_COUNT;++k){vec4 hQ=uShadowTexelPadProjections[k];float hR=hQ.x*dv.x+(hQ.y*dv.y+(hQ.z*dv.z+hQ.w));\n#ifdef MOBILE\nhR*=.001+hO;\n#else\nhR*=.0005+0.5*hO;\n#endif\nhighp vec4 hS=h(uShadowMatrices[k],dv-hR*hu);hV[k]=hS.xyz/hS.w;}highp vec4 hW;\n#if SHADOW_COUNT > 0\nhW=hT(tDepth0,hV[0].xy,uInvShadowMatrices[0]);ss.eE[0]=length(dv.xyz-hW.xyz);\n#endif\n#if SHADOW_COUNT > 1\nhW=hT(tDepth1,hV[1].xy,uInvShadowMatrices[1]);ss.eE[1]=length(dv.xyz-hW.xyz);\n#endif\n#if SHADOW_COUNT > 2\nhW=hT(tDepth2,hV[2].xy,uInvShadowMatrices[2]);ss.eE[2]=length(dv.xyz-hW.xyz);\n#endif\nfor(int k=SHADOW_COUNT;k<LIGHT_COUNT;++k){ss.eE[k]=1.0;}}\n#endif\n#endif\n",
            "matskin.glsl": "\n#ifdef SKIN\n#ifndef SKIN_NO_SUBDERMIS_TEX\nuniform vec4 uTexRangeSubdermis;\n#endif\n#ifndef SKIN_NO_TRANSLUCENCY_TEX\nuniform vec4 uTexRangeTranslucency;\n#endif\n#ifndef SKIN_NO_FUZZ_TEX\nuniform vec4 uTexRangeFuzz;\n#endif\nuniform vec4 uTransColor;uniform vec4 uFresnelColor;uniform vec3 uSubdermisColor;uniform float uTransScatter;uniform float uFresnelOcc;uniform float uFresnelGlossMask;uniform float uTransSky;uniform float uFresnelIntegral;uniform float uTransIntegral;uniform float uSkinTransDepth;uniform float uSkinShadowBlur;uniform float uNormalSmooth;struct dX{vec3 hX;vec3 hY,hZ,ic,he;vec3 ec,eh,id;vec3 ie;vec3 ih;vec3 ii;vec3 ij;float ik;float il;float im;float eC;};void dZ(out dX s){vec4 m;\n#ifdef SKIN_NO_SUBDERMIS_TEX\ns.hX=uSubdermisColor;s.im=1.0;\n#else \nm=dM(d,uTexRangeSubdermis);s.hX=dG(m.xyz);s.im=m.w*m.w;\n#endif\ns.ij=uTransColor.rgb;s.ik=uTransScatter;\n#ifdef SKIN_VERSION_1\ns.eC=uSkinShadowBlur*s.im;\n#else \ns.il=max(max(s.ij.r,s.ij.g),s.ij.b)*uTransColor.a;float io=max(s.hX.r,max(s.hX.g,s.hX.b));io=1.0-io;io*=io;io*=io;io*=io;io=1.0-(io*io);s.im*=io;s.eC=uSkinShadowBlur*s.im*dot(s.hX.rgb,vec3(0.333,0.334,0.333));\n#endif\n#ifndef SKIN_NO_TRANSLUCENCY_TEX\nm=dM(d,uTexRangeTranslucency);s.ij*=dG(m.xyz);\n#endif\ns.ie=hF(tNormal,d,uNormalSmooth*s.im);vec3 iu,iv,iA;fK(iu,iv,iA,s.ie);s.eh=s.hY=iu+iv+iA;\n#ifdef SKIN_VERSION_1 \ns.ec=fQ(iu,iv,iA,vec3(1.0,0.6667,0.25),s.hX);\n#else\ns.ec=fQ(iu,iv,iA,vec3(1.0,0.6667,0.25),s.hX*0.2+vec3(0.1));\n#endif\n#ifdef SKIN_VERSION_1\nvec3 iB,iC,iD;fK(iB,iC,iD,-s.ie);s.id=fO(iB,iC,iD,vec3(1.0,0.4444,0.0625),s.ik);s.id*=uTransSky;\n#else \ns.id=vec3(0.0);\n#endif\ns.hZ=s.ic=s.he=vec3(0.0);s.hX*=0.5;s.ik*=0.5;s.ih=uFresnelColor.rgb;s.ii=uFresnelColor.aaa*vec3(1.0,0.5,0.25);\n#ifndef SKIN_NO_FUZZ_TEX\nm=dM(d,uTexRangeFuzz);s.ih*=dG(m.rgb);\n#endif\n}void eK(inout dX s,float iE,float iF,vec3 eH,vec3 dI,vec3 eJ){float fk=dot(eH,dI);float fl=dot(eH,s.ie);float eN=saturate((1.0/3.1415926)*fk);float hi=iE*iE;hi*=hi;hi=saturate(6.0*hi);\n#ifdef SKIN_VERSION_1 \nvec3 iG=fB(fl,s.hX);\n#else \nvec3 iG=fj(fk,fl,s.hX);\n#endif\nfloat iH=fA(-fl,s.ik);vec3 ic=vec3(iH*iH);\n#ifdef SKIN_VERSION_1\n#ifdef SHADOW_COUNT\nvec3 iI=vec3(iE);float iJ=saturate(hi-2.0*(iE*iE));iI+=iJ*s.hX;float iK=iE;\n#endif\n#else\n#ifdef SHADOW_COUNT\nvec3 iI;highp vec3 iL=(0.995*s.hX)+vec3(0.005,0.005,0.005);highp vec3 iM=vec3(1.0)-iL;iL=mix(iL,iM,iE);float iN=sqrt(iE);vec3 iO=2.0*vec3(1.0-iN);iN=1.0-iN;iN=(1.0-iN*iN);iI=saturate(pow(iL*iN,iO));highp float iP=0.35/(uSkinTransDepth+0.001);highp float iQ=saturate(iF*iP);iQ=saturate(1.0-iQ);iQ*=iQ;highp vec3 iR=vec3((-3.0*iQ)+3.15);highp vec3 iS=(0.9975*s.ij)+vec3(0.0025,0.0025,0.0025);highp float io=saturate(10.0*dot(iS,iS));vec3 iK=pow(iS*iQ,iR)*io;\n#else \nic=vec3(0.0);\n#endif\n#endif\nfloat hj=fA(fl,s.ii.z);\n#ifdef SHADOW_COUNT\nvec3 hk=mix(vec3(1.0),iI,uFresnelOcc);vec3 he=hj*hk;\n#else\nvec3 he=vec3(hj);\n#endif\n#ifdef SHADOW_COUNT\niG*=iI;eN*=hi;ic*=iK;\n#endif\ns.he=he*eJ+s.he;s.ic=ic*eJ+s.ic;s.hZ=iG*eJ+s.hZ;s.hY=eN*eJ+s.hY;}void eQ(out vec3 ei,out vec3 diff_extra,inout dX s,vec3 dO,vec3 dI,float dQ){s.he*=uFresnelIntegral;float fH=dot(dO,dI);vec2 hl=fG(vec2(fH,fH),s.ii.xy);s.he=s.eh*hl.x+(s.he*hl.y);s.he*=s.ih;float hm=saturate(1.0+-uFresnelGlossMask*dQ);s.he*=hm*hm;s.ic=s.ic*uTransIntegral;\n#ifdef SKIN_VERSION_1\ns.hZ=(s.hZ*fD(s.hX))+s.ec;\n#else\ns.hZ=(s.hZ*fv(s.hX))+s.ec;\n#endif\nei=mix(s.hY,s.hZ,s.im);\n#ifdef SKIN_VERSION_1\ns.ic=(s.ic+s.id)*s.ij;diff_extra=(s.he+s.ic)*s.im;\n#else\nei+=s.ic*s.il;diff_extra=s.he*s.im;\n#endif\n}\n#endif\n",
            "matstrips.glsl": "\n#ifdef STRIPVIEW\nuniform float uStrips[5];uniform vec2 uStripRes;struct dT{float io[5];float bg;};void dV(out dT iT,inout float dQ,inout vec3 dP){highp vec2 hA=gl_FragCoord.xy*uStripRes-vec2(1.0,1.0);hA.x+=0.25*hA.y;iT.io[0]=step(hA.x,uStrips[0]);iT.io[1]=step(hA.x,uStrips[1]);iT.io[2]=step(hA.x,uStrips[2]);iT.io[3]=step(hA.x,uStrips[3]);iT.io[4]=step(hA.x,uStrips[4]);iT.bg=1.0-iT.io[4];iT.io[4]-=iT.io[3];iT.io[3]-=iT.io[2];iT.io[2]-=iT.io[1];iT.io[1]-=iT.io[0];bool iU=iT.io[4]>0.0;dQ=iU?0.5:dQ;dP=iU?vec3(0.1):dP;}vec3 eX(dT iT,vec3 dI,vec3 dF,vec3 dP,float dQ,vec3 ei,vec3 el,vec3 iV){return iT.io[0]*(dI*0.5+vec3(0.5))+iT.io[1]*dF+iT.io[2]*dP+vec3(iT.io[3]*dQ)+iT.io[4]*(vec3(0.12)+0.3*ei+el)+iT.bg*iV;}\n#endif\n",
            "matvert.glsl": "precision highp float;uniform mat4 uModelViewProjectionMatrix;uniform mat4 uSkyMatrix;uniform vec2 uUVOffset;attribute vec3 vPosition;attribute vec2 vTexCoord;attribute vec2 vTangent;attribute vec2 vBitangent;attribute vec2 vNormal;\n#ifdef VERTEX_COLOR\nattribute vec4 vColor;\n#endif\n#ifdef TEXCOORD_SECONDARY\nattribute vec2 vTexCoord2;\n#endif\nvarying highp vec3 dv;varying mediump vec2 d;varying mediump vec3 dA;varying mediump vec3 dB;varying mediump vec3 dC;\n#ifdef VERTEX_COLOR\nvarying lowp vec4 dD;\n#endif\n#ifdef TEXCOORD_SECONDARY\nvarying mediump vec2 dE;\n#endif\nvec3 iW(vec2 v){bool iX=(v.y>(32767.1/65535.0));v.y=iX?(v.y-(32768.0/65535.0)):v.y;vec3 r;r.xy=(2.0*65535.0/32767.0)*v-vec2(1.0);r.z=sqrt(clamp(1.0-dot(r.xy,r.xy),0.0,1.0));r.z=iX?-r.z:r.z;return r;}vec4 h(mat4 i,vec3 p){return i[0]*p.x+(i[1]*p.y+(i[2]*p.z+i[3]));}vec3 u(mat4 i,vec3 v){return i[0].xyz*v.x+i[1].xyz*v.y+i[2].xyz*v.z;}void main(void){gl_Position=h(uModelViewProjectionMatrix,vPosition.xyz);d=vTexCoord+uUVOffset;dA=u(uSkyMatrix,iW(vTangent));dB=u(uSkyMatrix,iW(vBitangent));dC=u(uSkyMatrix,iW(vNormal));dv=h(uSkyMatrix,vPosition.xyz).xyz;\n#ifdef VERTEX_COLOR\ndD=vColor;\n#endif\n#ifdef TEXCOORD_SECONDARY\ndE=vTexCoord2;\n#endif\n}",
            "postaa.glsl": "precision mediump float;uniform sampler2D tInput;varying vec2 j;void main(void){gl_FragColor=texture2D(tInput,j);}",
            "postfrag.glsl": "precision mediump float;uniform sampler2D tInput;\n#ifdef BLOOM\nuniform sampler2D tBloom;\n#endif\n#ifdef GRAIN\nuniform sampler2D tGrain;\n#endif\n#ifdef COLOR_LUT\nuniform sampler2D tLUT;\n#endif\nuniform vec3 uScale;uniform vec3 uBias;uniform vec3 uSaturation;uniform vec4 uSharpenKernel;uniform vec3 uSharpness;uniform vec3 uBloomColor;uniform vec4 uVignetteAspect;uniform vec4 uVignette;uniform vec4 uGrainCoord;uniform vec2 uGrainScaleBias;varying vec2 j;vec3 iY(vec3 c){vec3 iZ=sqrt(c);return(iZ-iZ*c)+c*(0.4672*c+vec3(0.5328));}void main(void){vec4 jc=texture2D(tInput,j);vec3 c=jc.xyz;\n#ifdef SHARPEN\nvec3 hM=texture2D(tInput,j+uSharpenKernel.xy).xyz;hM+=texture2D(tInput,j-uSharpenKernel.xy).xyz;hM+=texture2D(tInput,j+uSharpenKernel.zw).xyz;hM+=texture2D(tInput,j-uSharpenKernel.zw).xyz;vec3 jd=uSharpness.x*c-uSharpness.y*hM;c+=clamp(jd,-uSharpness.z,uSharpness.z);\n#endif\n#ifdef BLOOM\nc+=uBloomColor*texture2D(tBloom,j).xyz;\n#endif\n#ifdef VIGNETTE\nvec2 je=j*uVignetteAspect.xy-uVignetteAspect.zw;vec3 v=clamp(vec3(1.0,1.0,1.0)-uVignette.xyz*dot(je,je),0.0,1.0);vec3 jf=v*v;jf*=v;c*=mix(v,jf,uVignette.w);\n#endif\n#ifdef SATURATION\nfloat gray=dot(c,vec3(0.3,0.59,0.11));c=mix(vec3(gray,gray,gray),c,uSaturation);\n#endif\n#ifdef CONTRAST\nc=c*uScale+uBias;\n#endif\n#ifdef GRAIN\nfloat jh=uGrainScaleBias.x*texture2D(tGrain,j*uGrainCoord.xy+uGrainCoord.zw).x+uGrainScaleBias.y;c+=c*jh;\n#endif\n#ifdef REINHARD\n{c*=1.8;float ji=dot(c,vec3(0.3333));c=clamp(c/(1.0+ji),0.0,1.0);}\n#elif defined(HEJL)\n{const highp float jj=0.22,jk=0.3,jl=.1,jm=0.2,jn=.01,jo=0.3;const highp float ju=1.25;highp vec3 eO=max(vec3(0.0),c-vec3(.004));c=(eO*((ju*jj)*eO+ju*vec3(jl*jk,jl*jk,jl*jk))+ju*vec3(jm*jn,jm*jn,jm*jn))/(eO*(jj*eO+vec3(jk,jk,jk))+vec3(jm*jo,jm*jo,jm*jo))-ju*vec3(jn/jo,jn/jo,jn/jo);}\n#endif\n#ifdef COLOR_LUT\nc=clamp(c,0.0,1.0);c=(255.0/256.0)*c+vec3(0.5/256.0);c.x=texture2D(tLUT,c.xx).x;c.y=texture2D(tLUT,c.yy).y;c.z=texture2D(tLUT,c.zz).z;c*=c;\n#endif\ngl_FragColor.xyz=iY(c);gl_FragColor.w=jc.w;}",
            "postvert.glsl": "precision highp float;attribute vec2 vCoord;varying vec2 j;void main(void){j=vCoord;gl_Position.xy=2.0*vCoord-vec2(1.0,1.0);gl_Position.zw=vec2(0.0,1.0);}",
            "shadowfloorfrag.glsl": "precision mediump float;varying highp vec3 dv;varying mediump vec2 jv;varying mediump vec3 dC;uniform vec3 uShadowCatcherParams;\n#ifdef LIGHT_COUNT\nuniform vec4 uLightPositions[LIGHT_COUNT];uniform vec3 uLightDirections[LIGHT_COUNT];uniform vec3 uLightColors[LIGHT_COUNT];uniform vec3 uLightParams[LIGHT_COUNT];uniform vec3 uLightSpot[LIGHT_COUNT];\n#endif\n#define saturate(x) clamp( x, 0.0, 1.0 )\n#define SHADOW_COMPARE(a,b) ((a) < (b) || (b) >= 1.0 ? 1.0 : 0.0)\n#define SHADOW_CLIP(c,v) ((c.x<0.0 || c.x>1.0 || c.y<0.0 || c.y>1.0) ? 1.0 : v)\n#include <matshadows.glsl>\nvoid main(void){ev eA;eB(eA,SHADOW_KERNEL);vec3 jA=vec3(0.0,0.0,0.0);vec3 jB=vec3(0.0,0.0,0.0);for(int k=0;k<SHADOW_COUNT;++k){vec3 eH=uLightPositions[k].xyz-dv*uLightPositions[k].w;float eI=inversesqrt(dot(eH,eH));eH*=eI;float a=saturate(uLightParams[k].z/eI);a=1.0+a*(uLightParams[k].x+uLightParams[k].y*a);float s=saturate(dot(eH,uLightDirections[k]));s=saturate(uLightSpot[k].y-uLightSpot[k].z*(1.0-s*s));vec3 jC=mix(uLightColors[k].xyz,vec3(1.0,1.0,1.0),uShadowCatcherParams.x);vec3 jD=(a*s)*jC;jD*=saturate(dot(eH,dC));jB+=jD;jA+=jD*eA.eL[k];}float jE=1.0e-4;vec3 r=(jA+jE)/(jB+jE);float jF=saturate(dot(jv,jv))*uShadowCatcherParams.z;r=mix(r,vec3(1.0,1.0,1.0),jF);r=mix(vec3(1.0,1.0,1.0),r,uShadowCatcherParams.y);gl_FragColor.xyz=r;gl_FragColor.w=1.0;}",
            "shadowfloorvert.glsl": "precision highp float;uniform mat4 uModelViewProjectionMatrix;uniform mat4 uModelSkyMatrix;uniform float uScale;attribute vec3 vPosition;varying highp vec3 dv;varying mediump vec2 jv;varying mediump vec3 dC;vec4 h(mat4 i,vec3 p){return i[0]*p.x+(i[1]*p.y+(i[2]*p.z+i[3]));}void main(void){jv=vPosition.xz;dC=normalize(uModelSkyMatrix[1].xyz);dv=h(uModelSkyMatrix,vPosition).xyz;gl_Position=h(uModelViewProjectionMatrix,vPosition);}",
            "shadowfrag.glsl": "precision highp float;varying vec2 jG;\n#ifdef ALPHA_TEST\nvarying mediump vec2 d;uniform sampler2D tAlbedo;\n#endif\nvec3 jH(float v){vec4 jI=vec4(1.0,255.0,65025.0,16581375.0)*v;jI=fract(jI);jI.xyz-=jI.yzw*(1.0/255.0);return jI.xyz;}void main(void){\n#ifdef ALPHA_TEST\nfloat e=texture2D(tAlbedo,d).a;if(e<0.5){discard;}\n#endif\n#ifdef SHADOW_NATIVE_DEPTH\ngl_FragColor.xyz=vec3(0.0,0.0,0.0);\n#else\ngl_FragColor.xyz=jH((jG.x/jG.y)*0.5+0.5);\n#endif\ngl_FragColor.w=0.0;}",
            "shadowvert.glsl": "precision highp float;attribute vec3 vPosition;attribute vec2 vTexCoord;uniform mat4 uMeshTransform;uniform mat4 uViewProjection;varying vec2 jG;\n#ifdef ALPHA_TEST\nvarying mediump vec2 d;uniform vec2 uUVOffset;\n#endif\nvec4 h(mat4 i,vec3 p){return i[0]*p.x+(i[1]*p.y+(i[2]*p.z+i[3]));}void main(void){vec3 p=h(uMeshTransform,vPosition).xyz;gl_Position=h(uViewProjection,p);jG=gl_Position.zw;\n#ifdef ALPHA_TEST\nd=vTexCoord+uUVOffset;\n#endif\n}",
            "sky.glsl": "precision highp float;uniform sampler2D tSkyTexture;uniform float uAlpha;varying vec2 d;void main(void){vec3 r=texture2D(tSkyTexture,d).xyz;gl_FragColor.xyz=r*r;gl_FragColor.w=uAlpha;}",
            "skySH.glsl": "precision mediump float;uniform vec4 uSkyCoefficients[9];uniform float uAlpha;varying vec3 jJ;void main(void){vec3 G=normalize(jJ);vec3 r=uSkyCoefficients[0].xyz;r+=uSkyCoefficients[1].xyz*G.y;r+=uSkyCoefficients[2].xyz*G.z;r+=uSkyCoefficients[3].xyz*G.x;vec3 swz=G.yyz*G.xzx;r+=uSkyCoefficients[4].xyz*swz.x;r+=uSkyCoefficients[5].xyz*swz.y;r+=uSkyCoefficients[7].xyz*swz.z;vec3 sqr=G*G;r+=uSkyCoefficients[6].xyz*(3.0*sqr.z-1.0);r+=uSkyCoefficients[8].xyz*(sqr.x-sqr.y);gl_FragColor.xyz=r;gl_FragColor.w=uAlpha;}",
            "skyvert.glsl": "precision highp float;uniform mat4 uInverseSkyMatrix;uniform mat4 uViewProjection;attribute vec3 vPosition;attribute vec2 vTexCoord;\n#if SKYMODE == 3\nvarying vec3 jJ;\n#else\nvarying vec2 d;\n#endif\nvec4 h(mat4 i,vec3 p){return i[0]*p.x+(i[1]*p.y+(i[2]*p.z+i[3]));}vec4 u(mat4 i,vec3 v){return i[0]*v.x+i[1]*v.y+i[2]*v.z;}void main(void){vec3 p=h(uInverseSkyMatrix,vPosition).xyz;gl_Position=u(uViewProjection,p);gl_Position.z-=(1.0/65535.0)*gl_Position.w;\n#if SKYMODE == 3\njJ=vPosition;jJ.xy+=1e-20*vTexCoord;\n#else\nd=vTexCoord;\n#endif\n}",
            "wirefrag.glsl": "precision highp float;uniform vec4 uStripParams;void main(void){vec2 c=gl_FragCoord.xy*uStripParams.xy-vec2(1.0,1.0);c.x+=0.25*c.y;float a=c.x<uStripParams.z?0.0:0.9;a=c.x<uStripParams.w?a:0.0;gl_FragColor=vec4(0.0,0.0,0.0,a);}",
            "wirevert.glsl": "precision highp float;uniform mat4 uModelViewProjectionMatrix;attribute vec3 vPosition;vec4 h(mat4 i,vec3 p){return i[0]*p.x+(i[1]*p.y+(i[2]*p.z+i[3]));}void main(void){gl_Position=h(uModelViewProjectionMatrix,vPosition);gl_Position.z+=-0.00005*gl_Position.w;}",
            nil: ""
        }
    }(fdage);