(function (exports, Laya) {
	'use strict';

	class MathUtils3D {
	    constructor() {
	    }
	    static isZero(v) {
	        return Math.abs(v) < MathUtils3D.zeroTolerance;
	    }
	    static nearEqual(n1, n2) {
	        if (MathUtils3D.isZero(n1 - n2))
	            return true;
	        return false;
	    }
	    static fastInvSqrt(value) {
	        if (MathUtils3D.isZero(value))
	            return value;
	        return 1.0 / Math.sqrt(value);
	    }
	}
	MathUtils3D.zeroTolerance = 1e-6;
	MathUtils3D.MaxValue = 3.40282347e+38;
	MathUtils3D.MinValue = -3.40282347e+38;

	class Vector2 {
	    constructor(x = 0, y = 0) {
	        this.x = x;
	        this.y = y;
	    }
	    setValue(x, y) {
	        this.x = x;
	        this.y = y;
	    }
	    static scale(a, b, out) {
	        out.x = a.x * b;
	        out.y = a.y * b;
	    }
	    fromArray(array, offset = 0) {
	        this.x = array[offset + 0];
	        this.y = array[offset + 1];
	    }
	    cloneTo(destObject) {
	        var destVector2 = destObject;
	        destVector2.x = this.x;
	        destVector2.y = this.y;
	    }
	    static dot(a, b) {
	        return (a.x * b.x) + (a.y * b.y);
	    }
	    static normalize(s, out) {
	        var x = s.x, y = s.y;
	        var len = x * x + y * y;
	        if (len > 0) {
	            len = 1 / Math.sqrt(len);
	            out.x = x * len;
	            out.y = y * len;
	        }
	    }
	    static scalarLength(a) {
	        var x = a.x, y = a.y;
	        return Math.sqrt(x * x + y * y);
	    }
	    clone() {
	        var destVector2 = new Vector2();
	        this.cloneTo(destVector2);
	        return destVector2;
	    }
	    forNativeElement(nativeElements = null) {
	        if (nativeElements) {
	            this.elements = nativeElements;
	            this.elements[0] = this.x;
	            this.elements[1] = this.y;
	        }
	        else {
	            this.elements = new Float32Array([this.x, this.y]);
	        }
	        Vector2.rewriteNumProperty(this, "x", 0);
	        Vector2.rewriteNumProperty(this, "y", 1);
	    }
	    static rewriteNumProperty(proto, name, index) {
	        Object["defineProperty"](proto, name, {
	            "get": function () {
	                return this.elements[index];
	            },
	            "set": function (v) {
	                this.elements[index] = v;
	            }
	        });
	    }
	}
	Vector2.ZERO = new Vector2(0.0, 0.0);
	Vector2.ONE = new Vector2(1.0, 1.0);

	class Vector4 {
	    constructor(x = 0, y = 0, z = 0, w = 0) {
	        this.x = x;
	        this.y = y;
	        this.z = z;
	        this.w = w;
	    }
	    setValue(x, y, z, w) {
	        this.x = x;
	        this.y = y;
	        this.z = z;
	        this.w = w;
	    }
	    fromArray(array, offset = 0) {
	        this.x = array[offset + 0];
	        this.y = array[offset + 1];
	        this.z = array[offset + 2];
	        this.w = array[offset + 3];
	    }
	    cloneTo(destObject) {
	        var destVector4 = destObject;
	        destVector4.x = this.x;
	        destVector4.y = this.y;
	        destVector4.z = this.z;
	        destVector4.w = this.w;
	    }
	    clone() {
	        var destVector4 = new Vector4();
	        this.cloneTo(destVector4);
	        return destVector4;
	    }
	    static lerp(a, b, t, out) {
	        var ax = a.x, ay = a.y, az = a.z, aw = a.w;
	        out.x = ax + t * (b.x - ax);
	        out.y = ay + t * (b.y - ay);
	        out.z = az + t * (b.z - az);
	        out.w = aw + t * (b.w - aw);
	    }
	    static transformByM4x4(vector4, m4x4, out) {
	        var vx = vector4.x;
	        var vy = vector4.y;
	        var vz = vector4.z;
	        var vw = vector4.w;
	        var me = m4x4.elements;
	        out.x = vx * me[0] + vy * me[4] + vz * me[8] + vw * me[12];
	        out.y = vx * me[1] + vy * me[5] + vz * me[9] + vw * me[13];
	        out.z = vx * me[2] + vy * me[6] + vz * me[10] + vw * me[14];
	        out.w = vx * me[3] + vy * me[7] + vz * me[11] + vw * me[15];
	    }
	    static equals(a, b) {
	        return MathUtils3D.nearEqual(Math.abs(a.x), Math.abs(b.x)) && MathUtils3D.nearEqual(Math.abs(a.y), Math.abs(b.y)) && MathUtils3D.nearEqual(Math.abs(a.z), Math.abs(b.z)) && MathUtils3D.nearEqual(Math.abs(a.w), Math.abs(b.w));
	    }
	    length() {
	        return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w);
	    }
	    lengthSquared() {
	        return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
	    }
	    static normalize(s, out) {
	        var len = s.length();
	        if (len > 0) {
	            out.x = s.x * len;
	            out.y = s.y * len;
	            out.z = s.z * len;
	            out.w = s.w * len;
	        }
	    }
	    static add(a, b, out) {
	        out.x = a.x + b.x;
	        out.y = a.y + b.y;
	        out.z = a.z + b.z;
	        out.w = a.w + b.w;
	    }
	    static subtract(a, b, out) {
	        out.x = a.x - b.x;
	        out.y = a.y - b.y;
	        out.z = a.z - b.z;
	        out.w = a.w - b.w;
	    }
	    static multiply(a, b, out) {
	        out.x = a.x * b.x;
	        out.y = a.y * b.y;
	        out.z = a.z * b.z;
	        out.w = a.w * b.w;
	    }
	    static scale(a, b, out) {
	        out.x = a.x * b;
	        out.y = a.y * b;
	        out.z = a.z * b;
	        out.w = a.w * b;
	    }
	    static Clamp(value, min, max, out) {
	        var x = value.x;
	        var y = value.y;
	        var z = value.z;
	        var w = value.w;
	        var mineX = min.x;
	        var mineY = min.y;
	        var mineZ = min.z;
	        var mineW = min.w;
	        var maxeX = max.x;
	        var maxeY = max.y;
	        var maxeZ = max.z;
	        var maxeW = max.w;
	        x = (x > maxeX) ? maxeX : x;
	        x = (x < mineX) ? mineX : x;
	        y = (y > maxeY) ? maxeY : y;
	        y = (y < mineY) ? mineY : y;
	        z = (z > maxeZ) ? maxeZ : z;
	        z = (z < mineZ) ? mineZ : z;
	        w = (w > maxeW) ? maxeW : w;
	        w = (w < mineW) ? mineW : w;
	        out.x = x;
	        out.y = y;
	        out.z = z;
	        out.w = w;
	    }
	    static distanceSquared(value1, value2) {
	        var x = value1.x - value2.x;
	        var y = value1.y - value2.y;
	        var z = value1.z - value2.z;
	        var w = value1.w - value2.w;
	        return (x * x) + (y * y) + (z * z) + (w * w);
	    }
	    static distance(value1, value2) {
	        var x = value1.x - value2.x;
	        var y = value1.y - value2.y;
	        var z = value1.z - value2.z;
	        var w = value1.w - value2.w;
	        return Math.sqrt((x * x) + (y * y) + (z * z) + (w * w));
	    }
	    static dot(a, b) {
	        return (a.x * b.x) + (a.y * b.y) + (a.z * b.z) + (a.w * b.w);
	    }
	    static min(a, b, out) {
	        out.x = Math.min(a.x, b.x);
	        out.y = Math.min(a.y, b.y);
	        out.z = Math.min(a.z, b.z);
	        out.w = Math.min(a.w, b.w);
	    }
	    static max(a, b, out) {
	        out.x = Math.max(a.x, b.x);
	        out.y = Math.max(a.y, b.y);
	        out.z = Math.max(a.z, b.z);
	        out.w = Math.max(a.w, b.w);
	    }
	    forNativeElement(nativeElements = null) {
	        if (nativeElements) {
	            this.elements = nativeElements;
	            this.elements[0] = this.x;
	            this.elements[1] = this.y;
	            this.elements[2] = this.z;
	            this.elements[3] = this.w;
	        }
	        else {
	            this.elements = new Float32Array([this.x, this.y, this.z, this.w]);
	        }
	        Vector2.rewriteNumProperty(this, "x", 0);
	        Vector2.rewriteNumProperty(this, "y", 1);
	        Vector2.rewriteNumProperty(this, "z", 2);
	        Vector2.rewriteNumProperty(this, "w", 3);
	    }
	}
	Vector4.ZERO = new Vector4();
	Vector4.ONE = new Vector4(1.0, 1.0, 1.0, 1.0);
	Vector4.UnitX = new Vector4(1.0, 0.0, 0.0, 0.0);
	Vector4.UnitY = new Vector4(0.0, 1.0, 0.0, 0.0);
	Vector4.UnitZ = new Vector4(0.0, 0.0, 1.0, 0.0);
	Vector4.UnitW = new Vector4(0.0, 0.0, 0.0, 1.0);

	class Vector3 {
	    constructor(x = 0, y = 0, z = 0, nativeElements = null) {
	        this.x = x;
	        this.y = y;
	        this.z = z;
	    }
	    static distanceSquared(value1, value2) {
	        var x = value1.x - value2.x;
	        var y = value1.y - value2.y;
	        var z = value1.z - value2.z;
	        return (x * x) + (y * y) + (z * z);
	    }
	    static distance(value1, value2) {
	        var x = value1.x - value2.x;
	        var y = value1.y - value2.y;
	        var z = value1.z - value2.z;
	        return Math.sqrt((x * x) + (y * y) + (z * z));
	    }
	    static min(a, b, out) {
	        out.x = Math.min(a.x, b.x);
	        out.y = Math.min(a.y, b.y);
	        out.z = Math.min(a.z, b.z);
	    }
	    static max(a, b, out) {
	        out.x = Math.max(a.x, b.x);
	        out.y = Math.max(a.y, b.y);
	        out.z = Math.max(a.z, b.z);
	    }
	    static transformQuat(source, rotation, out) {
	        var x = source.x, y = source.y, z = source.z, qx = rotation.x, qy = rotation.y, qz = rotation.z, qw = rotation.w, ix = qw * x + qy * z - qz * y, iy = qw * y + qz * x - qx * z, iz = qw * z + qx * y - qy * x, iw = -qx * x - qy * y - qz * z;
	        out.x = ix * qw + iw * -qx + iy * -qz - iz * -qy;
	        out.y = iy * qw + iw * -qy + iz * -qx - ix * -qz;
	        out.z = iz * qw + iw * -qz + ix * -qy - iy * -qx;
	    }
	    static scalarLength(a) {
	        var x = a.x, y = a.y, z = a.z;
	        return Math.sqrt(x * x + y * y + z * z);
	    }
	    static scalarLengthSquared(a) {
	        var x = a.x, y = a.y, z = a.z;
	        return x * x + y * y + z * z;
	    }
	    static normalize(s, out) {
	        var x = s.x, y = s.y, z = s.z;
	        var len = x * x + y * y + z * z;
	        if (len > 0) {
	            len = 1 / Math.sqrt(len);
	            out.x = x * len;
	            out.y = y * len;
	            out.z = z * len;
	        }
	    }
	    static multiply(a, b, out) {
	        out.x = a.x * b.x;
	        out.y = a.y * b.y;
	        out.z = a.z * b.z;
	    }
	    static scale(a, b, out) {
	        out.x = a.x * b;
	        out.y = a.y * b;
	        out.z = a.z * b;
	    }
	    static lerp(a, b, t, out) {
	        var ax = a.x, ay = a.y, az = a.z;
	        out.x = ax + t * (b.x - ax);
	        out.y = ay + t * (b.y - ay);
	        out.z = az + t * (b.z - az);
	    }
	    static transformV3ToV3(vector, transform, result) {
	        var intermediate = Vector3._tempVector4;
	        Vector3.transformV3ToV4(vector, transform, intermediate);
	        result.x = intermediate.x;
	        result.y = intermediate.y;
	        result.z = intermediate.z;
	    }
	    static transformV3ToV4(vector, transform, result) {
	        var vectorX = vector.x;
	        var vectorY = vector.y;
	        var vectorZ = vector.z;
	        var transformElem = transform.elements;
	        result.x = (vectorX * transformElem[0]) + (vectorY * transformElem[4]) + (vectorZ * transformElem[8]) + transformElem[12];
	        result.y = (vectorX * transformElem[1]) + (vectorY * transformElem[5]) + (vectorZ * transformElem[9]) + transformElem[13];
	        result.z = (vectorX * transformElem[2]) + (vectorY * transformElem[6]) + (vectorZ * transformElem[10]) + transformElem[14];
	        result.w = (vectorX * transformElem[3]) + (vectorY * transformElem[7]) + (vectorZ * transformElem[11]) + transformElem[15];
	    }
	    static TransformNormal(normal, transform, result) {
	        var normalX = normal.x;
	        var normalY = normal.y;
	        var normalZ = normal.z;
	        var transformElem = transform.elements;
	        result.x = (normalX * transformElem[0]) + (normalY * transformElem[4]) + (normalZ * transformElem[8]);
	        result.y = (normalX * transformElem[1]) + (normalY * transformElem[5]) + (normalZ * transformElem[9]);
	        result.z = (normalX * transformElem[2]) + (normalY * transformElem[6]) + (normalZ * transformElem[10]);
	    }
	    static transformCoordinate(coordinate, transform, result) {
	        var coordinateX = coordinate.x;
	        var coordinateY = coordinate.y;
	        var coordinateZ = coordinate.z;
	        var transformElem = transform.elements;
	        var w = ((coordinateX * transformElem[3]) + (coordinateY * transformElem[7]) + (coordinateZ * transformElem[11]) + transformElem[15]);
	        result.x = (coordinateX * transformElem[0]) + (coordinateY * transformElem[4]) + (coordinateZ * transformElem[8]) + transformElem[12] / w;
	        result.y = (coordinateX * transformElem[1]) + (coordinateY * transformElem[5]) + (coordinateZ * transformElem[9]) + transformElem[13] / w;
	        result.z = (coordinateX * transformElem[2]) + (coordinateY * transformElem[6]) + (coordinateZ * transformElem[10]) + transformElem[14] / w;
	    }
	    static Clamp(value, min, max, out) {
	        var x = value.x;
	        var y = value.y;
	        var z = value.z;
	        var mineX = min.x;
	        var mineY = min.y;
	        var mineZ = min.z;
	        var maxeX = max.x;
	        var maxeY = max.y;
	        var maxeZ = max.z;
	        x = (x > maxeX) ? maxeX : x;
	        x = (x < mineX) ? mineX : x;
	        y = (y > maxeY) ? maxeY : y;
	        y = (y < mineY) ? mineY : y;
	        z = (z > maxeZ) ? maxeZ : z;
	        z = (z < mineZ) ? mineZ : z;
	        out.x = x;
	        out.y = y;
	        out.z = z;
	    }
	    static add(a, b, out) {
	        out.x = a.x + b.x;
	        out.y = a.y + b.y;
	        out.z = a.z + b.z;
	    }
	    static subtract(a, b, o) {
	        o.x = a.x - b.x;
	        o.y = a.y - b.y;
	        o.z = a.z - b.z;
	    }
	    static cross(a, b, o) {
	        var ax = a.x, ay = a.y, az = a.z, bx = b.x, by = b.y, bz = b.z;
	        o.x = ay * bz - az * by;
	        o.y = az * bx - ax * bz;
	        o.z = ax * by - ay * bx;
	    }
	    static dot(a, b) {
	        return (a.x * b.x) + (a.y * b.y) + (a.z * b.z);
	    }
	    static equals(a, b) {
	        return MathUtils3D.nearEqual(a.x, b.x) && MathUtils3D.nearEqual(a.y, b.y) && MathUtils3D.nearEqual(a.z, b.z);
	    }
	    setValue(x, y, z) {
	        this.x = x;
	        this.y = y;
	        this.z = z;
	    }
	    fromArray(array, offset = 0) {
	        this.x = array[offset + 0];
	        this.y = array[offset + 1];
	        this.z = array[offset + 2];
	    }
	    cloneTo(destObject) {
	        var destVector3 = destObject;
	        destVector3.x = this.x;
	        destVector3.y = this.y;
	        destVector3.z = this.z;
	    }
	    clone() {
	        var destVector3 = new Vector3();
	        this.cloneTo(destVector3);
	        return destVector3;
	    }
	    toDefault() {
	        this.x = 0;
	        this.y = 0;
	        this.z = 0;
	    }
	    forNativeElement(nativeElements = null) {
	        if (nativeElements) {
	            this.elements = nativeElements;
	            this.elements[0] = this.x;
	            this.elements[1] = this.y;
	            this.elements[2] = this.z;
	        }
	        else {
	            this.elements = new Float32Array([this.x, this.y, this.z]);
	        }
	        Vector2.rewriteNumProperty(this, "x", 0);
	        Vector2.rewriteNumProperty(this, "y", 1);
	        Vector2.rewriteNumProperty(this, "z", 2);
	    }
	}
	Vector3._tempVector4 = new Vector4();
	Vector3._ZERO = new Vector3(0.0, 0.0, 0.0);
	Vector3._ONE = new Vector3(1.0, 1.0, 1.0);
	Vector3._NegativeUnitX = new Vector3(-1, 0, 0);
	Vector3._UnitX = new Vector3(1, 0, 0);
	Vector3._UnitY = new Vector3(0, 1, 0);
	Vector3._UnitZ = new Vector3(0, 0, 1);
	Vector3._ForwardRH = new Vector3(0, 0, -1);
	Vector3._ForwardLH = new Vector3(0, 0, 1);
	Vector3._Up = new Vector3(0, 1, 0);

	class Config3D {
	    constructor() {
	        this._defaultPhysicsMemory = 16;
	        this._maxLightCount = 32;
	        this._lightClusterCount = new Vector3(12, 12, 12);
	        this._editerEnvironment = false;
	        this.isAntialias = true;
	        this.isAlpha = false;
	        this.premultipliedAlpha = true;
	        this.isStencil = true;
	        this.enbaleMultiLight = true;
	        this.octreeCulling = false;
	        this.octreeInitialSize = 64.0;
	        this.octreeInitialCenter = new Vector3(0, 0, 0);
	        this.octreeMinNodeSize = 2.0;
	        this.octreeLooseness = 1.25;
	        this.debugFrustumCulling = false;
	        this._maxAreaLightCountPerClusterAverage = Math.min(Math.floor(2048 / this._lightClusterCount.z - 1) * 4, this._maxLightCount);
	    }
	    get defaultPhysicsMemory() {
	        return this._defaultPhysicsMemory;
	    }
	    set defaultPhysicsMemory(value) {
	        if (value < 16)
	            throw "defaultPhysicsMemory must large than 16M";
	        this._defaultPhysicsMemory = value;
	    }
	    get maxLightCount() {
	        return this._maxLightCount;
	    }
	    set maxLightCount(value) {
	        if (value > 2048) {
	            this._maxLightCount = 2048;
	            console.warn("Config3D: maxLightCount must less equal 2048.");
	        }
	        else {
	            this._maxLightCount = value;
	        }
	    }
	    get lightClusterCount() {
	        return this._lightClusterCount;
	    }
	    set lightClusterCount(value) {
	        if (value.x > 128 || value.y > 128 || value.z > 128) {
	            this._lightClusterCount.setValue(Math.min(value.x, 128), Math.min(value.y, 128), Math.min(value.z, 128));
	            console.warn("Config3D: lightClusterCount X and Y、Z must less equal 128.");
	        }
	        else {
	            value.cloneTo(this._lightClusterCount);
	        }
	        var maxAreaLightCountWithZ = Math.floor(2048 / this._lightClusterCount.z - 1) * 4;
	        if (maxAreaLightCountWithZ < this._maxLightCount)
	            console.warn("Config3D: if the area light(PointLight、SpotLight) count is large than " + maxAreaLightCountWithZ + ",maybe the far away culster will ingonre some light.");
	        this._maxAreaLightCountPerClusterAverage = Math.min(maxAreaLightCountWithZ, this._maxLightCount);
	    }
	    _checkMaxLightCountPerCluster(maxLightCountPerCluster, clusterCountZ) {
	        return Math.ceil((maxLightCountPerCluster / 4) + 1) * clusterCountZ < 2048;
	    }
	    cloneTo(dest) {
	        var destConfig3D = dest;
	        destConfig3D._defaultPhysicsMemory = this._defaultPhysicsMemory;
	        destConfig3D._editerEnvironment = this._editerEnvironment;
	        destConfig3D.isAntialias = this.isAntialias;
	        destConfig3D.isAlpha = this.isAlpha;
	        destConfig3D.premultipliedAlpha = this.premultipliedAlpha;
	        destConfig3D.isStencil = this.isStencil;
	        destConfig3D.octreeCulling = this.octreeCulling;
	        this.octreeInitialCenter.cloneTo(destConfig3D.octreeInitialCenter);
	        destConfig3D.octreeInitialSize = this.octreeInitialSize;
	        destConfig3D.octreeMinNodeSize = this.octreeMinNodeSize;
	        destConfig3D.octreeLooseness = this.octreeLooseness;
	        destConfig3D.debugFrustumCulling = this.debugFrustumCulling;
	        destConfig3D.maxLightCount = this.maxLightCount;
	        destConfig3D.enbaleMultiLight = this.enbaleMultiLight;
	        var lightClusterCount = destConfig3D.lightClusterCount;
	        this.lightClusterCount.cloneTo(lightClusterCount);
	        destConfig3D.lightClusterCount = lightClusterCount;
	    }
	    clone() {
	        var dest = new Config3D();
	        this.cloneTo(dest);
	        return dest;
	    }
	}
	Config3D._config = new Config3D();
	window.Config3D = Config3D;

	class ILaya3D {
	}
	ILaya3D.Scene3D = null;
	ILaya3D.MeshRenderStaticBatchManager = null;
	ILaya3D.MeshRenderDynamicBatchManager = null;
	ILaya3D.SubMeshDynamicBatch = null;
	ILaya3D.Laya3D = null;
	ILaya3D.Matrix4x4 = null;

	class KeyframeNode {
	    constructor() {
	        this._ownerPath = [];
	        this._propertys = [];
	        this._keyFrames = [];
	    }
	    get ownerPathCount() {
	        return this._ownerPath.length;
	    }
	    get propertyCount() {
	        return this._propertys.length;
	    }
	    get keyFramesCount() {
	        return this._keyFrames.length;
	    }
	    _setOwnerPathCount(value) {
	        this._ownerPath.length = value;
	    }
	    _setOwnerPathByIndex(index, value) {
	        this._ownerPath[index] = value;
	    }
	    _joinOwnerPath(sep) {
	        return this._ownerPath.join(sep);
	    }
	    _setPropertyCount(value) {
	        this._propertys.length = value;
	    }
	    _setPropertyByIndex(index, value) {
	        this._propertys[index] = value;
	    }
	    _joinProperty(sep) {
	        return this._propertys.join(sep);
	    }
	    _setKeyframeCount(value) {
	        this._keyFrames.length = value;
	    }
	    _setKeyframeByIndex(index, value) {
	        this._keyFrames[index] = value;
	    }
	    getOwnerPathByIndex(index) {
	        return this._ownerPath[index];
	    }
	    getPropertyByIndex(index) {
	        return this._propertys[index];
	    }
	    getKeyframeByIndex(index) {
	        return this._keyFrames[index];
	    }
	}
	if (window.conch && window.conchKeyframeNode) {
	    KeyframeNode = window.conchKeyframeNode;
	}
	if (window.qq && window.qq.webglPlus) {
	    KeyframeNode = window.qq.webglPlus.conchKeyframeNode;
	}

	class AnimationEvent {
	    constructor() {
	    }
	}

	class Keyframe {
	    constructor() {
	    }
	    cloneTo(destObject) {
	        var destKeyFrame = destObject;
	        destKeyFrame.time = this.time;
	    }
	    clone() {
	        var dest = new Keyframe();
	        this.cloneTo(dest);
	        return dest;
	    }
	}

	class FloatKeyframe extends Keyframe {
	    constructor() {
	        super();
	    }
	    cloneTo(destObject) {
	        super.cloneTo(destObject);
	        var destKeyFrame = destObject;
	        destKeyFrame.inTangent = this.inTangent;
	        destKeyFrame.outTangent = this.outTangent;
	        destKeyFrame.value = this.value;
	    }
	}
	if (window.conch && window.conchFloatKeyframe) {
	    FloatKeyframe = window.conchFloatKeyframe;
	}
	if (window.qq && window.qq.webglPlus) {
	    FloatKeyframe = window.qq.webglPlus.conchFloatKeyframe;
	}

	class Matrix3x3 {
	    constructor() {
	        var e = this.elements = new Float32Array(9);
	        e[0] = 1;
	        e[1] = 0;
	        e[2] = 0;
	        e[3] = 0;
	        e[4] = 1;
	        e[5] = 0;
	        e[6] = 0;
	        e[7] = 0;
	        e[8] = 1;
	    }
	    static createRotationQuaternion(rotation, out) {
	        var rotX = rotation.x;
	        var rotY = rotation.y;
	        var rotZ = rotation.z;
	        var rotW = rotation.w;
	        var xx = rotX * rotX;
	        var yy = rotY * rotY;
	        var zz = rotZ * rotZ;
	        var xy = rotX * rotY;
	        var zw = rotZ * rotW;
	        var zx = rotZ * rotX;
	        var yw = rotY * rotW;
	        var yz = rotY * rotZ;
	        var xw = rotX * rotW;
	        var resultE = out.elements;
	        resultE[0] = 1.0 - (2.0 * (yy + zz));
	        resultE[1] = 2.0 * (xy + zw);
	        resultE[2] = 2.0 * (zx - yw);
	        resultE[3] = 2.0 * (xy - zw);
	        resultE[4] = 1.0 - (2.0 * (zz + xx));
	        resultE[5] = 2.0 * (yz + xw);
	        resultE[6] = 2.0 * (zx + yw);
	        resultE[7] = 2.0 * (yz - xw);
	        resultE[8] = 1.0 - (2.0 * (yy + xx));
	    }
	    static createFromTranslation(trans, out) {
	        var e = out.elements;
	        out[0] = 1;
	        out[1] = 0;
	        out[2] = 0;
	        out[3] = 0;
	        out[4] = 1;
	        out[5] = 0;
	        out[6] = trans.x;
	        out[7] = trans.y;
	        out[8] = 1;
	    }
	    static createFromRotation(rad, out) {
	        var e = out.elements;
	        var s = Math.sin(rad), c = Math.cos(rad);
	        e[0] = c;
	        e[1] = s;
	        e[2] = 0;
	        e[3] = -s;
	        e[4] = c;
	        e[5] = 0;
	        e[6] = 0;
	        e[7] = 0;
	        e[8] = 1;
	    }
	    static createFromScaling(scale, out) {
	        var e = out.elements;
	        e[0] = scale.x;
	        e[1] = 0;
	        e[2] = 0;
	        e[3] = 0;
	        e[4] = scale.y;
	        e[5] = 0;
	        e[6] = 0;
	        e[7] = 0;
	        e[8] = scale.z;
	    }
	    static createFromMatrix4x4(sou, out) {
	        var souE = sou.elements;
	        var outE = out.elements;
	        outE[0] = souE[0];
	        outE[1] = souE[1];
	        outE[2] = souE[2];
	        outE[3] = souE[4];
	        outE[4] = souE[5];
	        outE[5] = souE[6];
	        outE[6] = souE[8];
	        outE[7] = souE[9];
	        outE[8] = souE[10];
	    }
	    static multiply(left, right, out) {
	        var l = left.elements;
	        var r = right.elements;
	        var e = out.elements;
	        var l11 = l[0], l12 = l[1], l13 = l[2];
	        var l21 = l[3], l22 = l[4], l23 = l[5];
	        var l31 = l[6], l32 = l[7], l33 = l[8];
	        var r11 = r[0], r12 = r[1], r13 = r[2];
	        var r21 = r[3], r22 = r[4], r23 = r[5];
	        var r31 = r[6], r32 = r[7], r33 = r[8];
	        e[0] = r11 * l11 + r12 * l21 + r13 * l31;
	        e[1] = r11 * l12 + r12 * l22 + r13 * r32;
	        e[2] = r11 * l13 + r12 * l23 + r13 * l33;
	        e[3] = r21 * l11 + r22 * l21 + r23 * l31;
	        e[4] = r21 * l12 + r22 * l22 + r23 * l32;
	        e[5] = r21 * l13 + r22 * l23 + r23 * l33;
	        e[6] = r31 * l11 + r32 * l21 + r33 * l31;
	        e[7] = r31 * l12 + r32 * l22 + r33 * l32;
	        e[8] = r31 * l13 + r32 * l23 + r33 * l33;
	    }
	    determinant() {
	        var f = this.elements;
	        var a00 = f[0], a01 = f[1], a02 = f[2];
	        var a10 = f[3], a11 = f[4], a12 = f[5];
	        var a20 = f[6], a21 = f[7], a22 = f[8];
	        return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20);
	    }
	    translate(trans, out) {
	        var e = out.elements;
	        var f = this.elements;
	        var a00 = f[0], a01 = f[1], a02 = f[2];
	        var a10 = f[3], a11 = f[4], a12 = f[5];
	        var a20 = f[6], a21 = f[7], a22 = f[8];
	        var x = trans.x, y = trans.y;
	        e[0] = a00;
	        e[1] = a01;
	        e[2] = a02;
	        e[3] = a10;
	        e[4] = a11;
	        e[5] = a12;
	        e[6] = x * a00 + y * a10 + a20;
	        e[7] = x * a01 + y * a11 + a21;
	        e[8] = x * a02 + y * a12 + a22;
	    }
	    rotate(rad, out) {
	        var e = out.elements;
	        var f = this.elements;
	        var a00 = f[0], a01 = f[1], a02 = f[2];
	        var a10 = f[3], a11 = f[4], a12 = f[5];
	        var a20 = f[6], a21 = f[7], a22 = f[8];
	        var s = Math.sin(rad);
	        var c = Math.cos(rad);
	        e[0] = c * a00 + s * a10;
	        e[1] = c * a01 + s * a11;
	        e[2] = c * a02 + s * a12;
	        e[3] = c * a10 - s * a00;
	        e[4] = c * a11 - s * a01;
	        e[5] = c * a12 - s * a02;
	        e[6] = a20;
	        e[7] = a21;
	        e[8] = a22;
	    }
	    scale(scale, out) {
	        var e = out.elements;
	        var f = this.elements;
	        var x = scale.x, y = scale.y;
	        e[0] = x * f[0];
	        e[1] = x * f[1];
	        e[2] = x * f[2];
	        e[3] = y * f[3];
	        e[4] = y * f[4];
	        e[5] = y * f[5];
	        e[6] = f[6];
	        e[7] = f[7];
	        e[8] = f[8];
	    }
	    invert(out) {
	        var e = out.elements;
	        var f = this.elements;
	        var a00 = f[0], a01 = f[1], a02 = f[2];
	        var a10 = f[3], a11 = f[4], a12 = f[5];
	        var a20 = f[6], a21 = f[7], a22 = f[8];
	        var b01 = a22 * a11 - a12 * a21;
	        var b11 = -a22 * a10 + a12 * a20;
	        var b21 = a21 * a10 - a11 * a20;
	        var det = a00 * b01 + a01 * b11 + a02 * b21;
	        if (!det) {
	            out = null;
	        }
	        det = 1.0 / det;
	        e[0] = b01 * det;
	        e[1] = (-a22 * a01 + a02 * a21) * det;
	        e[2] = (a12 * a01 - a02 * a11) * det;
	        e[3] = b11 * det;
	        e[4] = (a22 * a00 - a02 * a20) * det;
	        e[5] = (-a12 * a00 + a02 * a10) * det;
	        e[6] = b21 * det;
	        e[7] = (-a21 * a00 + a01 * a20) * det;
	        e[8] = (a11 * a00 - a01 * a10) * det;
	    }
	    transpose(out) {
	        var e = out.elements;
	        var f = this.elements;
	        if (out === this) {
	            var a01 = f[1], a02 = f[2], a12 = f[5];
	            e[1] = f[3];
	            e[2] = f[6];
	            e[3] = a01;
	            e[5] = f[7];
	            e[6] = a02;
	            e[7] = a12;
	        }
	        else {
	            e[0] = f[0];
	            e[1] = f[3];
	            e[2] = f[6];
	            e[3] = f[1];
	            e[4] = f[4];
	            e[5] = f[7];
	            e[6] = f[2];
	            e[7] = f[5];
	            e[8] = f[8];
	        }
	    }
	    identity() {
	        var e = this.elements;
	        e[0] = 1;
	        e[1] = 0;
	        e[2] = 0;
	        e[3] = 0;
	        e[4] = 1;
	        e[5] = 0;
	        e[6] = 0;
	        e[7] = 0;
	        e[8] = 1;
	    }
	    cloneTo(destObject) {
	        var i, s, d;
	        s = this.elements;
	        d = destObject.elements;
	        if (s === d) {
	            return;
	        }
	        for (i = 0; i < 9; ++i) {
	            d[i] = s[i];
	        }
	    }
	    clone() {
	        var dest = new Matrix3x3();
	        this.cloneTo(dest);
	        return dest;
	    }
	    static lookAt(eye, target, up, out) {
	        Vector3.subtract(eye, target, Matrix3x3._tempV30);
	        Vector3.normalize(Matrix3x3._tempV30, Matrix3x3._tempV30);
	        Vector3.cross(up, Matrix3x3._tempV30, Matrix3x3._tempV31);
	        Vector3.normalize(Matrix3x3._tempV31, Matrix3x3._tempV31);
	        Vector3.cross(Matrix3x3._tempV30, Matrix3x3._tempV31, Matrix3x3._tempV32);
	        var v0 = Matrix3x3._tempV30;
	        var v1 = Matrix3x3._tempV31;
	        var v2 = Matrix3x3._tempV32;
	        var me = out.elements;
	        me[0] = v1.x;
	        me[3] = v1.y;
	        me[6] = v1.z;
	        me[1] = v2.x;
	        me[4] = v2.y;
	        me[7] = v2.z;
	        me[2] = v0.x;
	        me[5] = v0.y;
	        me[8] = v0.z;
	    }
	}
	Matrix3x3.DEFAULT = new Matrix3x3();
	Matrix3x3._tempV30 = new Vector3();
	Matrix3x3._tempV31 = new Vector3();
	Matrix3x3._tempV32 = new Vector3();

	class Quaternion {
	    constructor(x = 0, y = 0, z = 0, w = 1, nativeElements = null) {
	        this.x = x;
	        this.y = y;
	        this.z = z;
	        this.w = w;
	    }
	    static createFromYawPitchRoll(yaw, pitch, roll, out) {
	        var halfRoll = roll * 0.5;
	        var halfPitch = pitch * 0.5;
	        var halfYaw = yaw * 0.5;
	        var sinRoll = Math.sin(halfRoll);
	        var cosRoll = Math.cos(halfRoll);
	        var sinPitch = Math.sin(halfPitch);
	        var cosPitch = Math.cos(halfPitch);
	        var sinYaw = Math.sin(halfYaw);
	        var cosYaw = Math.cos(halfYaw);
	        out.x = (cosYaw * sinPitch * cosRoll) + (sinYaw * cosPitch * sinRoll);
	        out.y = (sinYaw * cosPitch * cosRoll) - (cosYaw * sinPitch * sinRoll);
	        out.z = (cosYaw * cosPitch * sinRoll) - (sinYaw * sinPitch * cosRoll);
	        out.w = (cosYaw * cosPitch * cosRoll) + (sinYaw * sinPitch * sinRoll);
	    }
	    static multiply(left, right, out) {
	        var lx = left.x;
	        var ly = left.y;
	        var lz = left.z;
	        var lw = left.w;
	        var rx = right.x;
	        var ry = right.y;
	        var rz = right.z;
	        var rw = right.w;
	        var a = (ly * rz - lz * ry);
	        var b = (lz * rx - lx * rz);
	        var c = (lx * ry - ly * rx);
	        var d = (lx * rx + ly * ry + lz * rz);
	        out.x = (lx * rw + rx * lw) + a;
	        out.y = (ly * rw + ry * lw) + b;
	        out.z = (lz * rw + rz * lw) + c;
	        out.w = lw * rw - d;
	    }
	    static arcTanAngle(x, y) {
	        if (x == 0) {
	            if (y == 1)
	                return Math.PI / 2;
	            return -Math.PI / 2;
	        }
	        if (x > 0)
	            return Math.atan(y / x);
	        if (x < 0) {
	            if (y > 0)
	                return Math.atan(y / x) + Math.PI;
	            return Math.atan(y / x) - Math.PI;
	        }
	        return 0;
	    }
	    static angleTo(from, location, angle) {
	        Vector3.subtract(location, from, Quaternion.TEMPVector30);
	        Vector3.normalize(Quaternion.TEMPVector30, Quaternion.TEMPVector30);
	        angle.x = Math.asin(Quaternion.TEMPVector30.y);
	        angle.y = Quaternion.arcTanAngle(-Quaternion.TEMPVector30.z, -Quaternion.TEMPVector30.x);
	    }
	    static createFromAxisAngle(axis, rad, out) {
	        rad = rad * 0.5;
	        var s = Math.sin(rad);
	        out.x = s * axis.x;
	        out.y = s * axis.y;
	        out.z = s * axis.z;
	        out.w = Math.cos(rad);
	    }
	    static createFromMatrix4x4(mat, out) {
	        var me = mat.elements;
	        var sqrt;
	        var half;
	        var scale = me[0] + me[5] + me[10];
	        if (scale > 0.0) {
	            sqrt = Math.sqrt(scale + 1.0);
	            out.w = sqrt * 0.5;
	            sqrt = 0.5 / sqrt;
	            out.x = (me[6] - me[9]) * sqrt;
	            out.y = (me[8] - me[2]) * sqrt;
	            out.z = (me[1] - me[4]) * sqrt;
	        }
	        else if ((me[0] >= me[5]) && (me[0] >= me[10])) {
	            sqrt = Math.sqrt(1.0 + me[0] - me[5] - me[10]);
	            half = 0.5 / sqrt;
	            out.x = 0.5 * sqrt;
	            out.y = (me[1] + me[4]) * half;
	            out.z = (me[2] + me[8]) * half;
	            out.w = (me[6] - me[9]) * half;
	        }
	        else if (me[5] > me[10]) {
	            sqrt = Math.sqrt(1.0 + me[5] - me[0] - me[10]);
	            half = 0.5 / sqrt;
	            out.x = (me[4] + me[1]) * half;
	            out.y = 0.5 * sqrt;
	            out.z = (me[9] + me[6]) * half;
	            out.w = (me[8] - me[2]) * half;
	        }
	        else {
	            sqrt = Math.sqrt(1.0 + me[10] - me[0] - me[5]);
	            half = 0.5 / sqrt;
	            out.x = (me[8] + me[2]) * half;
	            out.y = (me[9] + me[6]) * half;
	            out.z = 0.5 * sqrt;
	            out.w = (me[1] - me[4]) * half;
	        }
	    }
	    static slerp(left, right, t, out) {
	        var ax = left.x, ay = left.y, az = left.z, aw = left.w, bx = right.x, by = right.y, bz = right.z, bw = right.w;
	        var omega, cosom, sinom, scale0, scale1;
	        cosom = ax * bx + ay * by + az * bz + aw * bw;
	        if (cosom < 0.0) {
	            cosom = -cosom;
	            bx = -bx;
	            by = -by;
	            bz = -bz;
	            bw = -bw;
	        }
	        if ((1.0 - cosom) > 0.000001) {
	            omega = Math.acos(cosom);
	            sinom = Math.sin(omega);
	            scale0 = Math.sin((1.0 - t) * omega) / sinom;
	            scale1 = Math.sin(t * omega) / sinom;
	        }
	        else {
	            scale0 = 1.0 - t;
	            scale1 = t;
	        }
	        out.x = scale0 * ax + scale1 * bx;
	        out.y = scale0 * ay + scale1 * by;
	        out.z = scale0 * az + scale1 * bz;
	        out.w = scale0 * aw + scale1 * bw;
	        return out;
	    }
	    static lerp(left, right, amount, out) {
	        var inverse = 1.0 - amount;
	        if (Quaternion.dot(left, right) >= 0) {
	            out.x = (inverse * left.x) + (amount * right.x);
	            out.y = (inverse * left.y) + (amount * right.y);
	            out.z = (inverse * left.z) + (amount * right.z);
	            out.w = (inverse * left.w) + (amount * right.w);
	        }
	        else {
	            out.x = (inverse * left.x) - (amount * right.x);
	            out.y = (inverse * left.y) - (amount * right.y);
	            out.z = (inverse * left.z) - (amount * right.z);
	            out.w = (inverse * left.w) - (amount * right.w);
	        }
	        out.normalize(out);
	    }
	    static add(left, right, out) {
	        out.x = left.x + right.x;
	        out.y = left.y + right.y;
	        out.z = left.z + right.z;
	        out.w = left.w + right.w;
	    }
	    static dot(left, right) {
	        return left.x * right.x + left.y * right.y + left.z * right.z + left.w * right.w;
	    }
	    scaling(scaling, out) {
	        out.x = this.x * scaling;
	        out.y = this.y * scaling;
	        out.z = this.z * scaling;
	        out.w = this.w * scaling;
	    }
	    normalize(out) {
	        var len = this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
	        if (len > 0) {
	            len = 1 / Math.sqrt(len);
	            out.x = this.x * len;
	            out.y = this.y * len;
	            out.z = this.z * len;
	            out.w = this.w * len;
	        }
	    }
	    length() {
	        return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w);
	    }
	    rotateX(rad, out) {
	        rad *= 0.5;
	        var bx = Math.sin(rad), bw = Math.cos(rad);
	        out.x = this.x * bw + this.w * bx;
	        out.y = this.y * bw + this.z * bx;
	        out.z = this.z * bw - this.y * bx;
	        out.w = this.w * bw - this.x * bx;
	    }
	    rotateY(rad, out) {
	        rad *= 0.5;
	        var by = Math.sin(rad), bw = Math.cos(rad);
	        out.x = this.x * bw - this.z * by;
	        out.y = this.y * bw + this.w * by;
	        out.z = this.z * bw + this.x * by;
	        out.w = this.w * bw - this.y * by;
	    }
	    rotateZ(rad, out) {
	        rad *= 0.5;
	        var bz = Math.sin(rad), bw = Math.cos(rad);
	        out.x = this.x * bw + this.y * bz;
	        out.y = this.y * bw - this.x * bz;
	        out.z = this.z * bw + this.w * bz;
	        out.w = this.w * bw - this.z * bz;
	    }
	    getYawPitchRoll(out) {
	        Vector3.transformQuat(Vector3._ForwardRH, this, Quaternion.TEMPVector31);
	        Vector3.transformQuat(Vector3._Up, this, Quaternion.TEMPVector32);
	        var upe = Quaternion.TEMPVector32;
	        Quaternion.angleTo(Vector3._ZERO, Quaternion.TEMPVector31, Quaternion.TEMPVector33);
	        var angle = Quaternion.TEMPVector33;
	        if (angle.x == Math.PI / 2) {
	            angle.y = Quaternion.arcTanAngle(upe.z, upe.x);
	            angle.z = 0;
	        }
	        else if (angle.x == -Math.PI / 2) {
	            angle.y = Quaternion.arcTanAngle(-upe.z, -upe.x);
	            angle.z = 0;
	        }
	        else {
	            ILaya3D.Matrix4x4.createRotationY(-angle.y, ILaya3D.Matrix4x4.TEMPMatrix0);
	            ILaya3D.Matrix4x4.createRotationX(-angle.x, ILaya3D.Matrix4x4.TEMPMatrix1);
	            Vector3.transformCoordinate(Quaternion.TEMPVector32, ILaya3D.Matrix4x4.TEMPMatrix0, Quaternion.TEMPVector32);
	            Vector3.transformCoordinate(Quaternion.TEMPVector32, ILaya3D.Matrix4x4.TEMPMatrix1, Quaternion.TEMPVector32);
	            angle.z = Quaternion.arcTanAngle(upe.y, -upe.x);
	        }
	        if (angle.y <= -Math.PI)
	            angle.y = Math.PI;
	        if (angle.z <= -Math.PI)
	            angle.z = Math.PI;
	        if (angle.y >= Math.PI && angle.z >= Math.PI) {
	            angle.y = 0;
	            angle.z = 0;
	            angle.x = Math.PI - angle.x;
	        }
	        var oe = out;
	        oe.x = angle.y;
	        oe.y = angle.x;
	        oe.z = angle.z;
	    }
	    invert(out) {
	        var a0 = this.x, a1 = this.y, a2 = this.z, a3 = this.w;
	        var dot = a0 * a0 + a1 * a1 + a2 * a2 + a3 * a3;
	        var invDot = dot ? 1.0 / dot : 0;
	        out.x = -a0 * invDot;
	        out.y = -a1 * invDot;
	        out.z = -a2 * invDot;
	        out.w = a3 * invDot;
	    }
	    identity() {
	        this.x = 0;
	        this.y = 0;
	        this.z = 0;
	        this.w = 1;
	    }
	    fromArray(array, offset = 0) {
	        this.x = array[offset + 0];
	        this.y = array[offset + 1];
	        this.z = array[offset + 2];
	        this.w = array[offset + 3];
	    }
	    cloneTo(destObject) {
	        if (this === destObject) {
	            return;
	        }
	        destObject.x = this.x;
	        destObject.y = this.y;
	        destObject.z = this.z;
	        destObject.w = this.w;
	    }
	    clone() {
	        var dest = new Quaternion();
	        this.cloneTo(dest);
	        return dest;
	    }
	    equals(b) {
	        return MathUtils3D.nearEqual(this.x, b.x) && MathUtils3D.nearEqual(this.y, b.y) && MathUtils3D.nearEqual(this.z, b.z) && MathUtils3D.nearEqual(this.w, b.w);
	    }
	    static rotationLookAt(forward, up, out) {
	        Quaternion.lookAt(Vector3._ZERO, forward, up, out);
	    }
	    static lookAt(eye, target, up, out) {
	        Matrix3x3.lookAt(eye, target, up, Quaternion._tempMatrix3x3);
	        Quaternion.rotationMatrix(Quaternion._tempMatrix3x3, out);
	    }
	    lengthSquared() {
	        return (this.x * this.x) + (this.y * this.y) + (this.z * this.z) + (this.w * this.w);
	    }
	    static invert(value, out) {
	        var lengthSq = value.lengthSquared();
	        if (!MathUtils3D.isZero(lengthSq)) {
	            lengthSq = 1.0 / lengthSq;
	            out.x = -value.x * lengthSq;
	            out.y = -value.y * lengthSq;
	            out.z = -value.z * lengthSq;
	            out.w = value.w * lengthSq;
	        }
	    }
	    static rotationMatrix(matrix3x3, out) {
	        var me = matrix3x3.elements;
	        var m11 = me[0];
	        var m12 = me[1];
	        var m13 = me[2];
	        var m21 = me[3];
	        var m22 = me[4];
	        var m23 = me[5];
	        var m31 = me[6];
	        var m32 = me[7];
	        var m33 = me[8];
	        var sqrt, half;
	        var scale = m11 + m22 + m33;
	        if (scale > 0) {
	            sqrt = Math.sqrt(scale + 1);
	            out.w = sqrt * 0.5;
	            sqrt = 0.5 / sqrt;
	            out.x = (m23 - m32) * sqrt;
	            out.y = (m31 - m13) * sqrt;
	            out.z = (m12 - m21) * sqrt;
	        }
	        else if ((m11 >= m22) && (m11 >= m33)) {
	            sqrt = Math.sqrt(1 + m11 - m22 - m33);
	            half = 0.5 / sqrt;
	            out.x = 0.5 * sqrt;
	            out.y = (m12 + m21) * half;
	            out.z = (m13 + m31) * half;
	            out.w = (m23 - m32) * half;
	        }
	        else if (m22 > m33) {
	            sqrt = Math.sqrt(1 + m22 - m11 - m33);
	            half = 0.5 / sqrt;
	            out.x = (m21 + m12) * half;
	            out.y = 0.5 * sqrt;
	            out.z = (m32 + m23) * half;
	            out.w = (m31 - m13) * half;
	        }
	        else {
	            sqrt = Math.sqrt(1 + m33 - m11 - m22);
	            half = 0.5 / sqrt;
	            out.x = (m31 + m13) * half;
	            out.y = (m32 + m23) * half;
	            out.z = 0.5 * sqrt;
	            out.w = (m12 - m21) * half;
	        }
	    }
	    forNativeElement(nativeElements = null) {
	        if (nativeElements) {
	            this.elements = nativeElements;
	            this.elements[0] = this.x;
	            this.elements[1] = this.y;
	            this.elements[2] = this.z;
	            this.elements[3] = this.w;
	        }
	        else {
	            this.elements = new Float32Array([this.x, this.y, this.z, this.w]);
	        }
	        Vector2.rewriteNumProperty(this, "x", 0);
	        Vector2.rewriteNumProperty(this, "y", 1);
	        Vector2.rewriteNumProperty(this, "z", 2);
	        Vector2.rewriteNumProperty(this, "w", 3);
	    }
	}
	Quaternion.TEMPVector30 = new Vector3();
	Quaternion.TEMPVector31 = new Vector3();
	Quaternion.TEMPVector32 = new Vector3();
	Quaternion.TEMPVector33 = new Vector3();
	Quaternion._tempMatrix3x3 = new Matrix3x3();
	Quaternion.DEFAULT = new Quaternion();
	Quaternion.NAN = new Quaternion(NaN, NaN, NaN, NaN);

	class QuaternionKeyframe extends Keyframe {
	    constructor() {
	        super();
	        this.inTangent = new Vector4();
	        this.outTangent = new Vector4();
	        this.value = new Quaternion();
	    }
	    cloneTo(dest) {
	        super.cloneTo(dest);
	        var destKeyFarme = dest;
	        this.inTangent.cloneTo(destKeyFarme.inTangent);
	        this.outTangent.cloneTo(destKeyFarme.outTangent);
	        this.value.cloneTo(destKeyFarme.value);
	    }
	}
	if (window.conch && window.conchFloatArrayKeyframe) {
	    QuaternionKeyframe = window.conchFloatArrayKeyframe;
	}
	if (window.qq && window.qq.webglPlus) {
	    QuaternionKeyframe = window.qq.webglPlus.conchFloatArrayKeyframe;
	}

	class Vector3Keyframe extends Keyframe {
	    constructor() {
	        super();
	        this.inTangent = new Vector3();
	        this.outTangent = new Vector3();
	        this.value = new Vector3();
	    }
	    cloneTo(dest) {
	        super.cloneTo(dest);
	        var destKeyFarme = dest;
	        this.inTangent.cloneTo(destKeyFarme.inTangent);
	        this.outTangent.cloneTo(destKeyFarme.outTangent);
	        this.value.cloneTo(destKeyFarme.value);
	    }
	}
	if (window.conch && window.conchFloatArrayKeyframe) {
	    Vector3Keyframe = window.conchFloatArrayKeyframe;
	}
	if (window.qq && window.qq.webglPlus) {
	    Vector3Keyframe = window.qq.webglPlus.conchFloatArrayKeyframe;
	}

	class ConchVector4 {
	    constructor(x = 0, y = 0, z = 0, w = 0) {
	        var v = this.elements = new Float32Array(4);
	        v[0] = x;
	        v[1] = y;
	        v[2] = z;
	        v[3] = w;
	    }
	    get x() {
	        return this.elements[0];
	    }
	    set x(value) {
	        this.elements[0] = value;
	    }
	    get y() {
	        return this.elements[1];
	    }
	    set y(value) {
	        this.elements[1] = value;
	    }
	    get z() {
	        return this.elements[2];
	    }
	    set z(value) {
	        this.elements[2] = value;
	    }
	    get w() {
	        return this.elements[3];
	    }
	    set w(value) {
	        this.elements[3] = value;
	    }
	    fromArray(array, offset = 0) {
	        this.elements[0] = array[offset + 0];
	        this.elements[1] = array[offset + 1];
	        this.elements[2] = array[offset + 2];
	        this.elements[3] = array[offset + 3];
	    }
	    cloneTo(destObject) {
	        var destVector4 = destObject;
	        var destE = destVector4.elements;
	        var s = this.elements;
	        destE[0] = s[0];
	        destE[1] = s[1];
	        destE[2] = s[2];
	        destE[3] = s[3];
	    }
	    clone() {
	        var destVector4 = new ConchVector4();
	        this.cloneTo(destVector4);
	        return destVector4;
	    }
	    static lerp(a, b, t, out) {
	        var e = out.elements;
	        var f = a.elements;
	        var g = b.elements;
	        var ax = f[0], ay = f[1], az = f[2], aw = f[3];
	        e[0] = ax + t * (g[0] - ax);
	        e[1] = ay + t * (g[1] - ay);
	        e[2] = az + t * (g[2] - az);
	        e[3] = aw + t * (g[3] - aw);
	    }
	    static transformByM4x4(vector4, m4x4, out) {
	        var ve = vector4.elements;
	        var vx = ve[0];
	        var vy = ve[1];
	        var vz = ve[2];
	        var vw = ve[3];
	        var me = m4x4.elements;
	        var oe = out.elements;
	        oe[0] = vx * me[0] + vy * me[4] + vz * me[8] + vw * me[12];
	        oe[1] = vx * me[1] + vy * me[5] + vz * me[9] + vw * me[13];
	        oe[2] = vx * me[2] + vy * me[6] + vz * me[10] + vw * me[14];
	        oe[3] = vx * me[3] + vy * me[7] + vz * me[11] + vw * me[15];
	    }
	    static equals(a, b) {
	        var ae = a.elements;
	        var be = b.elements;
	        return MathUtils3D.nearEqual(Math.abs(ae[0]), Math.abs(be[0])) && MathUtils3D.nearEqual(Math.abs(ae[1]), Math.abs(be[1])) && MathUtils3D.nearEqual(Math.abs(ae[2]), Math.abs(be[2])) && MathUtils3D.nearEqual(Math.abs(ae[3]), Math.abs(be[3]));
	    }
	    length() {
	        return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w);
	    }
	    lengthSquared() {
	        return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
	    }
	    static normalize(s, out) {
	        var se = s.elements;
	        var oe = out.elements;
	        var len = s.length();
	        if (len > 0) {
	            oe[0] = se[0] * len;
	            oe[1] = se[1] * len;
	            oe[2] = se[2] * len;
	            oe[3] = se[3] * len;
	        }
	    }
	    static add(a, b, out) {
	        var oe = out.elements;
	        var ae = a.elements;
	        var be = b.elements;
	        oe[0] = ae[0] + be[0];
	        oe[1] = ae[1] + be[1];
	        oe[2] = ae[2] + be[2];
	        oe[3] = ae[3] + be[3];
	    }
	    static subtract(a, b, out) {
	        var oe = out.elements;
	        var ae = a.elements;
	        var be = b.elements;
	        oe[0] = ae[0] - be[0];
	        oe[1] = ae[1] - be[1];
	        oe[2] = ae[2] - be[2];
	        oe[3] = ae[3] - be[3];
	    }
	    static multiply(a, b, out) {
	        var oe = out.elements;
	        var ae = a.elements;
	        var be = b.elements;
	        oe[0] = ae[0] * be[0];
	        oe[1] = ae[1] * be[1];
	        oe[2] = ae[2] * be[2];
	        oe[3] = ae[3] * be[3];
	    }
	    static scale(a, b, out) {
	        var oe = out.elements;
	        var ae = a.elements;
	        oe[0] = ae[0] * b;
	        oe[1] = ae[1] * b;
	        oe[2] = ae[2] * b;
	        oe[3] = ae[3] * b;
	    }
	    static Clamp(value, min, max, out) {
	        var valuee = value.elements;
	        var x = valuee[0];
	        var y = valuee[1];
	        var z = valuee[2];
	        var w = valuee[3];
	        var mine = min.elements;
	        var mineX = mine[0];
	        var mineY = mine[1];
	        var mineZ = mine[2];
	        var mineW = mine[3];
	        var maxe = max.elements;
	        var maxeX = maxe[0];
	        var maxeY = maxe[1];
	        var maxeZ = maxe[2];
	        var maxeW = maxe[3];
	        var oute = out.elements;
	        x = (x > maxeX) ? maxeX : x;
	        x = (x < mineX) ? mineX : x;
	        y = (y > maxeY) ? maxeY : y;
	        y = (y < mineY) ? mineY : y;
	        z = (z > maxeZ) ? maxeZ : z;
	        z = (z < mineZ) ? mineZ : z;
	        w = (w > maxeW) ? maxeW : w;
	        w = (w < mineW) ? mineW : w;
	        oute[0] = x;
	        oute[1] = y;
	        oute[2] = z;
	        oute[3] = w;
	    }
	    static distanceSquared(value1, value2) {
	        var value1e = value1.elements;
	        var value2e = value2.elements;
	        var x = value1e[0] - value2e[0];
	        var y = value1e[1] - value2e[1];
	        var z = value1e[2] - value2e[2];
	        var w = value1e[3] - value2e[3];
	        return (x * x) + (y * y) + (z * z) + (w * w);
	    }
	    static distance(value1, value2) {
	        var value1e = value1.elements;
	        var value2e = value2.elements;
	        var x = value1e[0] - value2e[0];
	        var y = value1e[1] - value2e[1];
	        var z = value1e[2] - value2e[2];
	        var w = value1e[3] - value2e[3];
	        return Math.sqrt((x * x) + (y * y) + (z * z) + (w * w));
	    }
	    static dot(a, b) {
	        var ae = a.elements;
	        var be = b.elements;
	        var r = (ae[0] * be[0]) + (ae[1] * be[1]) + (ae[2] * be[2]) + (ae[3] * be[3]);
	        return r;
	    }
	    static min(a, b, out) {
	        var e = out.elements;
	        var f = a.elements;
	        var g = b.elements;
	        e[0] = Math.min(f[0], g[0]);
	        e[1] = Math.min(f[1], g[1]);
	        e[2] = Math.min(f[2], g[2]);
	        e[3] = Math.min(f[3], g[3]);
	    }
	    static max(a, b, out) {
	        var e = out.elements;
	        var f = a.elements;
	        var g = b.elements;
	        e[0] = Math.max(f[0], g[0]);
	        e[1] = Math.max(f[1], g[1]);
	        e[2] = Math.max(f[2], g[2]);
	        e[3] = Math.max(f[3], g[3]);
	    }
	}
	ConchVector4.ZERO = new ConchVector4();
	ConchVector4.ONE = new ConchVector4(1.0, 1.0, 1.0, 1.0);
	ConchVector4.UnitX = new ConchVector4(1.0, 0.0, 0.0, 0.0);
	ConchVector4.UnitY = new ConchVector4(0.0, 1.0, 0.0, 0.0);
	ConchVector4.UnitZ = new ConchVector4(0.0, 0.0, 1.0, 0.0);
	ConchVector4.UnitW = new ConchVector4(0.0, 0.0, 0.0, 1.0);

	class ConchVector3 {
	    constructor(x = 0, y = 0, z = 0, nativeElements = null) {
	        var v;
	        if (nativeElements) {
	            v = nativeElements;
	        }
	        else {
	            v = new Float32Array(3);
	        }
	        this.elements = v;
	        v[0] = x;
	        v[1] = y;
	        v[2] = z;
	    }
	    static distanceSquared(value1, value2) {
	        var value1e = value1.elements;
	        var value2e = value2.elements;
	        var x = value1e[0] - value2e[0];
	        var y = value1e[1] - value2e[1];
	        var z = value1e[2] - value2e[2];
	        return (x * x) + (y * y) + (z * z);
	    }
	    static distance(value1, value2) {
	        var value1e = value1.elements;
	        var value2e = value2.elements;
	        var x = value1e[0] - value2e[0];
	        var y = value1e[1] - value2e[1];
	        var z = value1e[2] - value2e[2];
	        return Math.sqrt((x * x) + (y * y) + (z * z));
	    }
	    static min(a, b, out) {
	        var e = out.elements;
	        var f = a.elements;
	        var g = b.elements;
	        e[0] = Math.min(f[0], g[0]);
	        e[1] = Math.min(f[1], g[1]);
	        e[2] = Math.min(f[2], g[2]);
	    }
	    static max(a, b, out) {
	        var e = out.elements;
	        var f = a.elements;
	        var g = b.elements;
	        e[0] = Math.max(f[0], g[0]);
	        e[1] = Math.max(f[1], g[1]);
	        e[2] = Math.max(f[2], g[2]);
	    }
	    static transformQuat(source, rotation, out) {
	        var destination = out.elements;
	        var se = source.elements;
	        var re = rotation.elements;
	        var x = se[0], y = se[1], z = se[2], qx = re[0], qy = re[1], qz = re[2], qw = re[3], ix = qw * x + qy * z - qz * y, iy = qw * y + qz * x - qx * z, iz = qw * z + qx * y - qy * x, iw = -qx * x - qy * y - qz * z;
	        destination[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy;
	        destination[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;
	        destination[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;
	    }
	    static scalarLength(a) {
	        var f = a.elements;
	        var x = f[0], y = f[1], z = f[2];
	        return Math.sqrt(x * x + y * y + z * z);
	    }
	    static scalarLengthSquared(a) {
	        var f = a.elements;
	        var x = f[0], y = f[1], z = f[2];
	        return x * x + y * y + z * z;
	    }
	    static normalize(s, out) {
	        var se = s.elements;
	        var oe = out.elements;
	        var x = se[0], y = se[1], z = se[2];
	        var len = x * x + y * y + z * z;
	        if (len > 0) {
	            len = 1 / Math.sqrt(len);
	            oe[0] = se[0] * len;
	            oe[1] = se[1] * len;
	            oe[2] = se[2] * len;
	        }
	    }
	    static multiply(a, b, out) {
	        var e = out.elements;
	        var f = a.elements;
	        var g = b.elements;
	        e[0] = f[0] * g[0];
	        e[1] = f[1] * g[1];
	        e[2] = f[2] * g[2];
	    }
	    static scale(a, b, out) {
	        var e = out.elements;
	        var f = a.elements;
	        e[0] = f[0] * b;
	        e[1] = f[1] * b;
	        e[2] = f[2] * b;
	    }
	    static lerp(a, b, t, out) {
	        var e = out.elements;
	        var f = a.elements;
	        var g = b.elements;
	        var ax = f[0], ay = f[1], az = f[2];
	        e[0] = ax + t * (g[0] - ax);
	        e[1] = ay + t * (g[1] - ay);
	        e[2] = az + t * (g[2] - az);
	    }
	    static transformV3ToV3(vector, transform, result) {
	        var intermediate = ConchVector3._tempVector4;
	        ConchVector3.transformV3ToV4(vector, transform, intermediate);
	        var intermediateElem = intermediate.elements;
	        var resultElem = result.elements;
	        resultElem[0] = intermediateElem[0];
	        resultElem[1] = intermediateElem[1];
	        resultElem[2] = intermediateElem[2];
	    }
	    static transformV3ToV4(vector, transform, result) {
	        var vectorElem = vector.elements;
	        var vectorX = vectorElem[0];
	        var vectorY = vectorElem[1];
	        var vectorZ = vectorElem[2];
	        var transformElem = transform.elements;
	        var resultElem = result.elements;
	        resultElem[0] = (vectorX * transformElem[0]) + (vectorY * transformElem[4]) + (vectorZ * transformElem[8]) + transformElem[12];
	        resultElem[1] = (vectorX * transformElem[1]) + (vectorY * transformElem[5]) + (vectorZ * transformElem[9]) + transformElem[13];
	        resultElem[2] = (vectorX * transformElem[2]) + (vectorY * transformElem[6]) + (vectorZ * transformElem[10]) + transformElem[14];
	        resultElem[3] = (vectorX * transformElem[3]) + (vectorY * transformElem[7]) + (vectorZ * transformElem[11]) + transformElem[15];
	    }
	    static TransformNormal(normal, transform, result) {
	        var normalElem = normal.elements;
	        var normalX = normalElem[0];
	        var normalY = normalElem[1];
	        var normalZ = normalElem[2];
	        var transformElem = transform.elements;
	        var resultElem = result.elements;
	        resultElem[0] = (normalX * transformElem[0]) + (normalY * transformElem[4]) + (normalZ * transformElem[8]);
	        resultElem[1] = (normalX * transformElem[1]) + (normalY * transformElem[5]) + (normalZ * transformElem[9]);
	        resultElem[2] = (normalX * transformElem[2]) + (normalY * transformElem[6]) + (normalZ * transformElem[10]);
	    }
	    static transformCoordinate(coordinate, transform, result) {
	        var coordinateElem = coordinate.elements;
	        var coordinateX = coordinateElem[0];
	        var coordinateY = coordinateElem[1];
	        var coordinateZ = coordinateElem[2];
	        var transformElem = transform.elements;
	        var w = ((coordinateX * transformElem[3]) + (coordinateY * transformElem[7]) + (coordinateZ * transformElem[11]) + transformElem[15]);
	        var resultElem = result.elements;
	        resultElem[0] = (coordinateX * transformElem[0]) + (coordinateY * transformElem[4]) + (coordinateZ * transformElem[8]) + transformElem[12] / w;
	        resultElem[1] = (coordinateX * transformElem[1]) + (coordinateY * transformElem[5]) + (coordinateZ * transformElem[9]) + transformElem[13] / w;
	        resultElem[2] = (coordinateX * transformElem[2]) + (coordinateY * transformElem[6]) + (coordinateZ * transformElem[10]) + transformElem[14] / w;
	    }
	    static Clamp(value, min, max, out) {
	        var valuee = value.elements;
	        var x = valuee[0];
	        var y = valuee[1];
	        var z = valuee[2];
	        var mine = min.elements;
	        var mineX = mine[0];
	        var mineY = mine[1];
	        var mineZ = mine[2];
	        var maxe = max.elements;
	        var maxeX = maxe[0];
	        var maxeY = maxe[1];
	        var maxeZ = maxe[2];
	        var oute = out.elements;
	        x = (x > maxeX) ? maxeX : x;
	        x = (x < mineX) ? mineX : x;
	        y = (y > maxeY) ? maxeY : y;
	        y = (y < mineY) ? mineY : y;
	        z = (z > maxeZ) ? maxeZ : z;
	        z = (z < mineZ) ? mineZ : z;
	        oute[0] = x;
	        oute[1] = y;
	        oute[2] = z;
	    }
	    static add(a, b, out) {
	        var e = out.elements;
	        var f = a.elements;
	        var g = b.elements;
	        e[0] = f[0] + g[0];
	        e[1] = f[1] + g[1];
	        e[2] = f[2] + g[2];
	    }
	    static subtract(a, b, o) {
	        var oe = o.elements;
	        var ae = a.elements;
	        var be = b.elements;
	        oe[0] = ae[0] - be[0];
	        oe[1] = ae[1] - be[1];
	        oe[2] = ae[2] - be[2];
	    }
	    static cross(a, b, o) {
	        var ae = a.elements;
	        var be = b.elements;
	        var oe = o.elements;
	        var ax = ae[0], ay = ae[1], az = ae[2], bx = be[0], by = be[1], bz = be[2];
	        oe[0] = ay * bz - az * by;
	        oe[1] = az * bx - ax * bz;
	        oe[2] = ax * by - ay * bx;
	    }
	    static dot(a, b) {
	        var ae = a.elements;
	        var be = b.elements;
	        var r = (ae[0] * be[0]) + (ae[1] * be[1]) + (ae[2] * be[2]);
	        return r;
	    }
	    static equals(a, b) {
	        var ae = a.elements;
	        var be = b.elements;
	        return MathUtils3D.nearEqual(ae[0], be[0]) && MathUtils3D.nearEqual(ae[1], be[1]) && MathUtils3D.nearEqual(ae[2], be[2]);
	    }
	    get x() {
	        return this.elements[0];
	    }
	    set x(value) {
	        this.elements[0] = value;
	    }
	    get y() {
	        return this.elements[1];
	    }
	    set y(value) {
	        this.elements[1] = value;
	    }
	    get z() {
	        return this.elements[2];
	    }
	    set z(value) {
	        this.elements[2] = value;
	    }
	    setValue(x, y, z) {
	        this.elements[0] = x;
	        this.elements[1] = y;
	        this.elements[2] = z;
	    }
	    fromArray(array, offset = 0) {
	        this.elements[0] = array[offset + 0];
	        this.elements[1] = array[offset + 1];
	        this.elements[2] = array[offset + 2];
	    }
	    cloneTo(destObject) {
	        var destVector3 = destObject;
	        var destE = destVector3.elements;
	        var s = this.elements;
	        destE[0] = s[0];
	        destE[1] = s[1];
	        destE[2] = s[2];
	    }
	    clone() {
	        var destVector3 = new ConchVector3();
	        this.cloneTo(destVector3);
	        return destVector3;
	    }
	    toDefault() {
	        this.elements[0] = 0;
	        this.elements[1] = 0;
	        this.elements[2] = 0;
	    }
	}
	ConchVector3._tempVector4 = new ConchVector4();
	ConchVector3.ZERO = new ConchVector3(0.0, 0.0, 0.0);
	ConchVector3.ONE = new ConchVector3(1.0, 1.0, 1.0);
	ConchVector3.NegativeUnitX = new ConchVector3(-1, 0, 0);
	ConchVector3.UnitX = new ConchVector3(1, 0, 0);
	ConchVector3.UnitY = new ConchVector3(0, 1, 0);
	ConchVector3.UnitZ = new ConchVector3(0, 0, 1);
	ConchVector3.ForwardRH = new ConchVector3(0, 0, -1);
	ConchVector3.ForwardLH = new ConchVector3(0, 0, 1);
	ConchVector3.Up = new ConchVector3(0, 1, 0);
	ConchVector3.NAN = new ConchVector3(NaN, NaN, NaN);

	class Matrix4x4 {
	    constructor(m11 = 1, m12 = 0, m13 = 0, m14 = 0, m21 = 0, m22 = 1, m23 = 0, m24 = 0, m31 = 0, m32 = 0, m33 = 1, m34 = 0, m41 = 0, m42 = 0, m43 = 0, m44 = 1, elements = null) {
	        var e = elements ? this.elements = elements : this.elements = new Float32Array(16);
	        e[0] = m11;
	        e[1] = m12;
	        e[2] = m13;
	        e[3] = m14;
	        e[4] = m21;
	        e[5] = m22;
	        e[6] = m23;
	        e[7] = m24;
	        e[8] = m31;
	        e[9] = m32;
	        e[10] = m33;
	        e[11] = m34;
	        e[12] = m41;
	        e[13] = m42;
	        e[14] = m43;
	        e[15] = m44;
	    }
	    static createRotationX(rad, out) {
	        var oe = out.elements;
	        var s = Math.sin(rad), c = Math.cos(rad);
	        oe[1] = oe[2] = oe[3] = oe[4] = oe[7] = oe[8] = oe[11] = oe[12] = oe[13] = oe[14] = 0;
	        oe[0] = oe[15] = 1;
	        oe[5] = oe[10] = c;
	        oe[6] = s;
	        oe[9] = -s;
	    }
	    static createRotationY(rad, out) {
	        var oe = out.elements;
	        var s = Math.sin(rad), c = Math.cos(rad);
	        oe[1] = oe[3] = oe[4] = oe[6] = oe[7] = oe[9] = oe[11] = oe[12] = oe[13] = oe[14] = 0;
	        oe[5] = oe[15] = 1;
	        oe[0] = oe[10] = c;
	        oe[2] = -s;
	        oe[8] = s;
	    }
	    static createRotationZ(rad, out) {
	        var oe = out.elements;
	        var s = Math.sin(rad), c = Math.cos(rad);
	        oe[2] = oe[3] = oe[6] = oe[7] = oe[8] = oe[9] = oe[11] = oe[12] = oe[13] = oe[14] = 0;
	        oe[10] = oe[15] = 1;
	        oe[0] = oe[5] = c;
	        oe[1] = s;
	        oe[4] = -s;
	    }
	    static createRotationYawPitchRoll(yaw, pitch, roll, result) {
	        Quaternion.createFromYawPitchRoll(yaw, pitch, roll, Matrix4x4._tempQuaternion);
	        Matrix4x4.createRotationQuaternion(Matrix4x4._tempQuaternion, result);
	    }
	    static createRotationAxis(axis, angle, result) {
	        var x = axis.x;
	        var y = axis.y;
	        var z = axis.z;
	        var cos = Math.cos(angle);
	        var sin = Math.sin(angle);
	        var xx = x * x;
	        var yy = y * y;
	        var zz = z * z;
	        var xy = x * y;
	        var xz = x * z;
	        var yz = y * z;
	        var resultE = result.elements;
	        resultE[3] = resultE[7] = resultE[11] = resultE[12] = resultE[13] = resultE[14] = 0;
	        resultE[15] = 1.0;
	        resultE[0] = xx + (cos * (1.0 - xx));
	        resultE[1] = (xy - (cos * xy)) + (sin * z);
	        resultE[2] = (xz - (cos * xz)) - (sin * y);
	        resultE[4] = (xy - (cos * xy)) - (sin * z);
	        resultE[5] = yy + (cos * (1.0 - yy));
	        resultE[6] = (yz - (cos * yz)) + (sin * x);
	        resultE[8] = (xz - (cos * xz)) + (sin * y);
	        resultE[9] = (yz - (cos * yz)) - (sin * x);
	        resultE[10] = zz + (cos * (1.0 - zz));
	    }
	    setRotation(rotation) {
	        var rotationX = rotation.x;
	        var rotationY = rotation.y;
	        var rotationZ = rotation.z;
	        var rotationW = rotation.w;
	        var xx = rotationX * rotationX;
	        var yy = rotationY * rotationY;
	        var zz = rotationZ * rotationZ;
	        var xy = rotationX * rotationY;
	        var zw = rotationZ * rotationW;
	        var zx = rotationZ * rotationX;
	        var yw = rotationY * rotationW;
	        var yz = rotationY * rotationZ;
	        var xw = rotationX * rotationW;
	        var e = this.elements;
	        e[0] = 1.0 - (2.0 * (yy + zz));
	        e[1] = 2.0 * (xy + zw);
	        e[2] = 2.0 * (zx - yw);
	        e[4] = 2.0 * (xy - zw);
	        e[5] = 1.0 - (2.0 * (zz + xx));
	        e[6] = 2.0 * (yz + xw);
	        e[8] = 2.0 * (zx + yw);
	        e[9] = 2.0 * (yz - xw);
	        e[10] = 1.0 - (2.0 * (yy + xx));
	    }
	    setPosition(position) {
	        var e = this.elements;
	        e[12] = position.x;
	        e[13] = position.y;
	        e[14] = position.z;
	    }
	    static createRotationQuaternion(rotation, result) {
	        var resultE = result.elements;
	        var rotationX = rotation.x;
	        var rotationY = rotation.y;
	        var rotationZ = rotation.z;
	        var rotationW = rotation.w;
	        var xx = rotationX * rotationX;
	        var yy = rotationY * rotationY;
	        var zz = rotationZ * rotationZ;
	        var xy = rotationX * rotationY;
	        var zw = rotationZ * rotationW;
	        var zx = rotationZ * rotationX;
	        var yw = rotationY * rotationW;
	        var yz = rotationY * rotationZ;
	        var xw = rotationX * rotationW;
	        resultE[3] = resultE[7] = resultE[11] = resultE[12] = resultE[13] = resultE[14] = 0;
	        resultE[15] = 1.0;
	        resultE[0] = 1.0 - (2.0 * (yy + zz));
	        resultE[1] = 2.0 * (xy + zw);
	        resultE[2] = 2.0 * (zx - yw);
	        resultE[4] = 2.0 * (xy - zw);
	        resultE[5] = 1.0 - (2.0 * (zz + xx));
	        resultE[6] = 2.0 * (yz + xw);
	        resultE[8] = 2.0 * (zx + yw);
	        resultE[9] = 2.0 * (yz - xw);
	        resultE[10] = 1.0 - (2.0 * (yy + xx));
	    }
	    static createTranslate(trans, out) {
	        var oe = out.elements;
	        oe[4] = oe[8] = oe[1] = oe[9] = oe[2] = oe[6] = oe[3] = oe[7] = oe[11] = 0;
	        oe[0] = oe[5] = oe[10] = oe[15] = 1;
	        oe[12] = trans.x;
	        oe[13] = trans.y;
	        oe[14] = trans.z;
	    }
	    static createScaling(scale, out) {
	        var oe = out.elements;
	        oe[0] = scale.x;
	        oe[5] = scale.y;
	        oe[10] = scale.z;
	        oe[1] = oe[4] = oe[8] = oe[12] = oe[9] = oe[13] = oe[2] = oe[6] = oe[14] = oe[3] = oe[7] = oe[11] = 0;
	        oe[15] = 1;
	    }
	    static multiply(left, right, out) {
	        var l = right.elements;
	        var r = left.elements;
	        var e = out.elements;
	        var l11 = l[0], l12 = l[1], l13 = l[2], l14 = l[3];
	        var l21 = l[4], l22 = l[5], l23 = l[6], l24 = l[7];
	        var l31 = l[8], l32 = l[9], l33 = l[10], l34 = l[11];
	        var l41 = l[12], l42 = l[13], l43 = l[14], l44 = l[15];
	        var r11 = r[0], r12 = r[1], r13 = r[2], r14 = r[3];
	        var r21 = r[4], r22 = r[5], r23 = r[6], r24 = r[7];
	        var r31 = r[8], r32 = r[9], r33 = r[10], r34 = r[11];
	        var r41 = r[12], r42 = r[13], r43 = r[14], r44 = r[15];
	        e[0] = (l11 * r11) + (l12 * r21) + (l13 * r31) + (l14 * r41);
	        e[1] = (l11 * r12) + (l12 * r22) + (l13 * r32) + (l14 * r42);
	        e[2] = (l11 * r13) + (l12 * r23) + (l13 * r33) + (l14 * r43);
	        e[3] = (l11 * r14) + (l12 * r24) + (l13 * r34) + (l14 * r44);
	        e[4] = (l21 * r11) + (l22 * r21) + (l23 * r31) + (l24 * r41);
	        e[5] = (l21 * r12) + (l22 * r22) + (l23 * r32) + (l24 * r42);
	        e[6] = (l21 * r13) + (l22 * r23) + (l23 * r33) + (l24 * r43);
	        e[7] = (l21 * r14) + (l22 * r24) + (l23 * r34) + (l24 * r44);
	        e[8] = (l31 * r11) + (l32 * r21) + (l33 * r31) + (l34 * r41);
	        e[9] = (l31 * r12) + (l32 * r22) + (l33 * r32) + (l34 * r42);
	        e[10] = (l31 * r13) + (l32 * r23) + (l33 * r33) + (l34 * r43);
	        e[11] = (l31 * r14) + (l32 * r24) + (l33 * r34) + (l34 * r44);
	        e[12] = (l41 * r11) + (l42 * r21) + (l43 * r31) + (l44 * r41);
	        e[13] = (l41 * r12) + (l42 * r22) + (l43 * r32) + (l44 * r42);
	        e[14] = (l41 * r13) + (l42 * r23) + (l43 * r33) + (l44 * r43);
	        e[15] = (l41 * r14) + (l42 * r24) + (l43 * r34) + (l44 * r44);
	    }
	    static multiplyForNative(left, right, out) {
	        Laya.LayaGL.instance.matrix4x4Multiply(left.elements, right.elements, out.elements);
	    }
	    static createFromQuaternion(rotation, out) {
	        var e = out.elements;
	        var x = rotation.x, y = rotation.y, z = rotation.z, w = rotation.w;
	        var x2 = x + x;
	        var y2 = y + y;
	        var z2 = z + z;
	        var xx = x * x2;
	        var yx = y * x2;
	        var yy = y * y2;
	        var zx = z * x2;
	        var zy = z * y2;
	        var zz = z * z2;
	        var wx = w * x2;
	        var wy = w * y2;
	        var wz = w * z2;
	        e[0] = 1 - yy - zz;
	        e[1] = yx + wz;
	        e[2] = zx - wy;
	        e[3] = 0;
	        e[4] = yx - wz;
	        e[5] = 1 - xx - zz;
	        e[6] = zy + wx;
	        e[7] = 0;
	        e[8] = zx + wy;
	        e[9] = zy - wx;
	        e[10] = 1 - xx - yy;
	        e[11] = 0;
	        e[12] = 0;
	        e[13] = 0;
	        e[14] = 0;
	        e[15] = 1;
	    }
	    static createAffineTransformation(trans, rot, scale, out) {
	        var oe = out.elements;
	        var x = rot.x, y = rot.y, z = rot.z, w = rot.w, x2 = x + x, y2 = y + y, z2 = z + z;
	        var xx = x * x2, xy = x * y2, xz = x * z2, yy = y * y2, yz = y * z2, zz = z * z2;
	        var wx = w * x2, wy = w * y2, wz = w * z2, sx = scale.x, sy = scale.y, sz = scale.z;
	        oe[0] = (1 - (yy + zz)) * sx;
	        oe[1] = (xy + wz) * sx;
	        oe[2] = (xz - wy) * sx;
	        oe[3] = 0;
	        oe[4] = (xy - wz) * sy;
	        oe[5] = (1 - (xx + zz)) * sy;
	        oe[6] = (yz + wx) * sy;
	        oe[7] = 0;
	        oe[8] = (xz + wy) * sz;
	        oe[9] = (yz - wx) * sz;
	        oe[10] = (1 - (xx + yy)) * sz;
	        oe[11] = 0;
	        oe[12] = trans.x;
	        oe[13] = trans.y;
	        oe[14] = trans.z;
	        oe[15] = 1;
	    }
	    static createLookAt(eye, target, up, out) {
	        var oE = out.elements;
	        var xaxis = Matrix4x4._tempVector0;
	        var yaxis = Matrix4x4._tempVector1;
	        var zaxis = Matrix4x4._tempVector2;
	        Vector3.subtract(eye, target, zaxis);
	        Vector3.normalize(zaxis, zaxis);
	        Vector3.cross(up, zaxis, xaxis);
	        Vector3.normalize(xaxis, xaxis);
	        Vector3.cross(zaxis, xaxis, yaxis);
	        out.identity();
	        oE[0] = xaxis.x;
	        oE[4] = xaxis.y;
	        oE[8] = xaxis.z;
	        oE[1] = yaxis.x;
	        oE[5] = yaxis.y;
	        oE[9] = yaxis.z;
	        oE[2] = zaxis.x;
	        oE[6] = zaxis.y;
	        oE[10] = zaxis.z;
	        oE[12] = -Vector3.dot(xaxis, eye);
	        oE[13] = -Vector3.dot(yaxis, eye);
	        oE[14] = -Vector3.dot(zaxis, eye);
	    }
	    static createPerspective(fov, aspect, znear, zfar, out) {
	        var yScale = 1.0 / Math.tan(fov * 0.5);
	        var xScale = yScale / aspect;
	        var halfWidth = znear / xScale;
	        var halfHeight = znear / yScale;
	        Matrix4x4.createPerspectiveOffCenter(-halfWidth, halfWidth, -halfHeight, halfHeight, znear, zfar, out);
	    }
	    static createPerspectiveOffCenter(left, right, bottom, top, znear, zfar, out) {
	        var oe = out.elements;
	        var zRange = zfar / (zfar - znear);
	        oe[1] = oe[2] = oe[3] = oe[4] = oe[6] = oe[7] = oe[12] = oe[13] = oe[15] = 0;
	        oe[0] = 2.0 * znear / (right - left);
	        oe[5] = 2.0 * znear / (top - bottom);
	        oe[8] = (left + right) / (right - left);
	        oe[9] = (top + bottom) / (top - bottom);
	        oe[10] = -zRange;
	        oe[11] = -1.0;
	        oe[14] = -znear * zRange;
	    }
	    static createOrthoOffCenter(left, right, bottom, top, znear, zfar, out) {
	        var oe = out.elements;
	        var zRange = 1.0 / (zfar - znear);
	        oe[1] = oe[2] = oe[3] = oe[4] = oe[6] = oe[8] = oe[7] = oe[9] = oe[11] = 0;
	        oe[15] = 1;
	        oe[0] = 2.0 / (right - left);
	        oe[5] = 2.0 / (top - bottom);
	        oe[10] = -zRange;
	        oe[12] = (left + right) / (left - right);
	        oe[13] = (top + bottom) / (bottom - top);
	        oe[14] = -znear * zRange;
	    }
	    getElementByRowColumn(row, column) {
	        if (row < 0 || row > 3)
	            throw new Error("row Rows and columns for matrices run from 0 to 3, inclusive.");
	        if (column < 0 || column > 3)
	            throw new Error("column Rows and columns for matrices run from 0 to 3, inclusive.");
	        return this.elements[(row * 4) + column];
	    }
	    setElementByRowColumn(row, column, value) {
	        if (row < 0 || row > 3)
	            throw new Error("row Rows and columns for matrices run from 0 to 3, inclusive.");
	        if (column < 0 || column > 3)
	            throw new Error("column Rows and columns for matrices run from 0 to 3, inclusive.");
	        this.elements[(row * 4) + column] = value;
	    }
	    equalsOtherMatrix(other) {
	        var e = this.elements;
	        var oe = other.elements;
	        return (MathUtils3D.nearEqual(e[0], oe[0]) && MathUtils3D.nearEqual(e[1], oe[1]) && MathUtils3D.nearEqual(e[2], oe[2]) && MathUtils3D.nearEqual(e[3], oe[3]) && MathUtils3D.nearEqual(e[4], oe[4]) && MathUtils3D.nearEqual(e[5], oe[5]) && MathUtils3D.nearEqual(e[6], oe[6]) && MathUtils3D.nearEqual(e[7], oe[7]) && MathUtils3D.nearEqual(e[8], oe[8]) && MathUtils3D.nearEqual(e[9], oe[9]) && MathUtils3D.nearEqual(e[10], oe[10]) && MathUtils3D.nearEqual(e[11], oe[11]) && MathUtils3D.nearEqual(e[12], oe[12]) && MathUtils3D.nearEqual(e[13], oe[13]) && MathUtils3D.nearEqual(e[14], oe[14]) && MathUtils3D.nearEqual(e[15], oe[15]));
	    }
	    decomposeTransRotScale(translation, rotation, scale) {
	        var rotationMatrix = Matrix4x4._tempMatrix4x4;
	        if (this.decomposeTransRotMatScale(translation, rotationMatrix, scale)) {
	            Quaternion.createFromMatrix4x4(rotationMatrix, rotation);
	            return true;
	        }
	        else {
	            rotation.identity();
	            return false;
	        }
	    }
	    decomposeTransRotMatScale(translation, rotationMatrix, scale) {
	        var e = this.elements;
	        var te = translation;
	        var re = rotationMatrix.elements;
	        var se = scale;
	        te.x = e[12];
	        te.y = e[13];
	        te.z = e[14];
	        var m11 = e[0], m12 = e[1], m13 = e[2];
	        var m21 = e[4], m22 = e[5], m23 = e[6];
	        var m31 = e[8], m32 = e[9], m33 = e[10];
	        var sX = se.x = Math.sqrt((m11 * m11) + (m12 * m12) + (m13 * m13));
	        var sY = se.y = Math.sqrt((m21 * m21) + (m22 * m22) + (m23 * m23));
	        var sZ = se.z = Math.sqrt((m31 * m31) + (m32 * m32) + (m33 * m33));
	        if (MathUtils3D.isZero(sX) || MathUtils3D.isZero(sY) || MathUtils3D.isZero(sZ)) {
	            re[1] = re[2] = re[3] = re[4] = re[6] = re[7] = re[8] = re[9] = re[11] = re[12] = re[13] = re[14] = 0;
	            re[0] = re[5] = re[10] = re[15] = 1;
	            return false;
	        }
	        var at = Matrix4x4._tempVector0;
	        at.x = m31 / sZ;
	        at.y = m32 / sZ;
	        at.z = m33 / sZ;
	        var tempRight = Matrix4x4._tempVector1;
	        tempRight.x = m11 / sX;
	        tempRight.y = m12 / sX;
	        tempRight.z = m13 / sX;
	        var up = Matrix4x4._tempVector2;
	        Vector3.cross(at, tempRight, up);
	        var right = Matrix4x4._tempVector1;
	        Vector3.cross(up, at, right);
	        re[3] = re[7] = re[11] = re[12] = re[13] = re[14] = 0;
	        re[15] = 1;
	        re[0] = right.x;
	        re[1] = right.y;
	        re[2] = right.z;
	        re[4] = up.x;
	        re[5] = up.y;
	        re[6] = up.z;
	        re[8] = at.x;
	        re[9] = at.y;
	        re[10] = at.z;
	        ((re[0] * m11 + re[1] * m12 + re[2] * m13) < 0.0) && (se.x = -sX);
	        ((re[4] * m21 + re[5] * m22 + re[6] * m23) < 0.0) && (se.y = -sY);
	        ((re[8] * m31 + re[9] * m32 + re[10] * m33) < 0.0) && (se.z = -sZ);
	        return true;
	    }
	    decomposeYawPitchRoll(yawPitchRoll) {
	        var pitch = Math.asin(-this.elements[9]);
	        yawPitchRoll.y = pitch;
	        var test = Math.cos(pitch);
	        if (test > MathUtils3D.zeroTolerance) {
	            yawPitchRoll.z = Math.atan2(this.elements[1], this.elements[5]);
	            yawPitchRoll.x = Math.atan2(this.elements[8], this.elements[10]);
	        }
	        else {
	            yawPitchRoll.z = Math.atan2(-this.elements[4], this.elements[0]);
	            yawPitchRoll.x = 0.0;
	        }
	    }
	    normalize() {
	        var v = this.elements;
	        var c = v[0], d = v[1], e = v[2], g = Math.sqrt(c * c + d * d + e * e);
	        if (g) {
	            if (g == 1)
	                return;
	        }
	        else {
	            v[0] = 0;
	            v[1] = 0;
	            v[2] = 0;
	            return;
	        }
	        g = 1 / g;
	        v[0] = c * g;
	        v[1] = d * g;
	        v[2] = e * g;
	    }
	    transpose() {
	        var e, t;
	        e = this.elements;
	        t = e[1];
	        e[1] = e[4];
	        e[4] = t;
	        t = e[2];
	        e[2] = e[8];
	        e[8] = t;
	        t = e[3];
	        e[3] = e[12];
	        e[12] = t;
	        t = e[6];
	        e[6] = e[9];
	        e[9] = t;
	        t = e[7];
	        e[7] = e[13];
	        e[13] = t;
	        t = e[11];
	        e[11] = e[14];
	        e[14] = t;
	        return this;
	    }
	    invert(out) {
	        var ae = this.elements;
	        var oe = out.elements;
	        var a00 = ae[0], a01 = ae[1], a02 = ae[2], a03 = ae[3], a10 = ae[4], a11 = ae[5], a12 = ae[6], a13 = ae[7], a20 = ae[8], a21 = ae[9], a22 = ae[10], a23 = ae[11], a30 = ae[12], a31 = ae[13], a32 = ae[14], a33 = ae[15], b00 = a00 * a11 - a01 * a10, b01 = a00 * a12 - a02 * a10, b02 = a00 * a13 - a03 * a10, b03 = a01 * a12 - a02 * a11, b04 = a01 * a13 - a03 * a11, b05 = a02 * a13 - a03 * a12, b06 = a20 * a31 - a21 * a30, b07 = a20 * a32 - a22 * a30, b08 = a20 * a33 - a23 * a30, b09 = a21 * a32 - a22 * a31, b10 = a21 * a33 - a23 * a31, b11 = a22 * a33 - a23 * a32, det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
	        if (Math.abs(det) === 0.0) {
	            return;
	        }
	        det = 1.0 / det;
	        oe[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
	        oe[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
	        oe[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
	        oe[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
	        oe[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
	        oe[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
	        oe[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
	        oe[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
	        oe[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
	        oe[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
	        oe[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
	        oe[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
	        oe[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
	        oe[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
	        oe[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
	        oe[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
	    }
	    static billboard(objectPosition, cameraPosition, cameraRight, cameraUp, cameraForward, mat) {
	        Vector3.subtract(objectPosition, cameraPosition, Matrix4x4._tempVector0);
	        var lengthSq = Vector3.scalarLengthSquared(Matrix4x4._tempVector0);
	        if (MathUtils3D.isZero(lengthSq)) {
	            Vector3.scale(cameraForward, -1, Matrix4x4._tempVector1);
	            Matrix4x4._tempVector1.cloneTo(Matrix4x4._tempVector0);
	        }
	        else {
	            Vector3.scale(Matrix4x4._tempVector0, 1 / Math.sqrt(lengthSq), Matrix4x4._tempVector0);
	        }
	        Vector3.cross(cameraUp, Matrix4x4._tempVector0, Matrix4x4._tempVector2);
	        Vector3.normalize(Matrix4x4._tempVector2, Matrix4x4._tempVector2);
	        Vector3.cross(Matrix4x4._tempVector0, Matrix4x4._tempVector2, Matrix4x4._tempVector3);
	        var crosse = Matrix4x4._tempVector2;
	        var finale = Matrix4x4._tempVector3;
	        var diffee = Matrix4x4._tempVector0;
	        var obpose = objectPosition;
	        var mate = mat.elements;
	        mate[0] = crosse.x;
	        mate[1] = crosse.y;
	        mate[2] = crosse.z;
	        mate[3] = 0.0;
	        mate[4] = finale.x;
	        mate[5] = finale.y;
	        mate[6] = finale.z;
	        mate[7] = 0.0;
	        mate[8] = diffee.x;
	        mate[9] = diffee.y;
	        mate[10] = diffee.z;
	        mate[11] = 0.0;
	        mate[12] = obpose.x;
	        mate[13] = obpose.y;
	        mate[14] = obpose.z;
	        mate[15] = 1.0;
	    }
	    identity() {
	        var e = this.elements;
	        e[1] = e[2] = e[3] = e[4] = e[6] = e[7] = e[8] = e[9] = e[11] = e[12] = e[13] = e[14] = 0;
	        e[0] = e[5] = e[10] = e[15] = 1;
	    }
	    cloneTo(destObject) {
	        var i, s, d;
	        s = this.elements;
	        d = destObject.elements;
	        if (s === d) {
	            return;
	        }
	        for (i = 0; i < 16; ++i) {
	            d[i] = s[i];
	        }
	    }
	    clone() {
	        var dest = new Matrix4x4();
	        this.cloneTo(dest);
	        return dest;
	    }
	    static translation(v3, out) {
	        var oe = out.elements;
	        oe[0] = oe[5] = oe[10] = oe[15] = 1;
	        oe[12] = v3.x;
	        oe[13] = v3.y;
	        oe[14] = v3.z;
	    }
	    getTranslationVector(out) {
	        var me = this.elements;
	        out.x = me[12];
	        out.y = me[13];
	        out.z = me[14];
	    }
	    setTranslationVector(translate) {
	        var me = this.elements;
	        var ve = translate;
	        me[12] = ve.x;
	        me[13] = ve.y;
	        me[14] = ve.z;
	    }
	    getForward(out) {
	        var me = this.elements;
	        out.x = -me[8];
	        out.y = -me[9];
	        out.z = -me[10];
	    }
	    setForward(forward) {
	        var me = this.elements;
	        me[8] = -forward.x;
	        me[9] = -forward.y;
	        me[10] = -forward.z;
	    }
	}
	Matrix4x4._tempMatrix4x4 = new Matrix4x4();
	Matrix4x4.TEMPMatrix0 = new Matrix4x4();
	Matrix4x4.TEMPMatrix1 = new Matrix4x4();
	Matrix4x4._tempVector0 = new Vector3();
	Matrix4x4._tempVector1 = new Vector3();
	Matrix4x4._tempVector2 = new Vector3();
	Matrix4x4._tempVector3 = new Vector3();
	Matrix4x4._tempQuaternion = new Quaternion();
	Matrix4x4.DEFAULT = new Matrix4x4();
	Matrix4x4.ZERO = new Matrix4x4(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);

	class ConchQuaternion {
	    constructor(x = 0, y = 0, z = 0, w = 1, nativeElements = null) {
	        var v;
	        if (nativeElements) {
	            v = nativeElements;
	        }
	        else {
	            v = new Float32Array(4);
	        }
	        v[0] = x;
	        v[1] = y;
	        v[2] = z;
	        v[3] = w;
	        this.elements = v;
	    }
	    static _dotArray(l, r) {
	        return l[0] * r[0] + l[1] * r[1] + l[2] * r[2] + l[3] * r[3];
	    }
	    static _normalizeArray(f, o) {
	        var x = f[0], y = f[1], z = f[2], w = f[3];
	        var len = x * x + y * y + z * z + w * w;
	        if (len > 0) {
	            len = 1 / Math.sqrt(len);
	            o[0] = x * len;
	            o[1] = y * len;
	            o[2] = z * len;
	            o[3] = w * len;
	        }
	    }
	    static _lerpArray(l, r, amount, o) {
	        var inverse = 1.0 - amount;
	        if (ConchQuaternion._dotArray(l, r) >= 0) {
	            o[0] = (inverse * l[0]) + (amount * r[0]);
	            o[1] = (inverse * l[1]) + (amount * r[1]);
	            o[2] = (inverse * l[2]) + (amount * r[2]);
	            o[3] = (inverse * l[3]) + (amount * r[3]);
	        }
	        else {
	            o[0] = (inverse * l[0]) - (amount * r[0]);
	            o[1] = (inverse * l[1]) - (amount * r[1]);
	            o[2] = (inverse * l[2]) - (amount * r[2]);
	            o[3] = (inverse * l[3]) - (amount * r[3]);
	        }
	        ConchQuaternion._normalizeArray(o, o);
	    }
	    static createFromYawPitchRoll(yaw, pitch, roll, out) {
	        var halfRoll = roll * 0.5;
	        var halfPitch = pitch * 0.5;
	        var halfYaw = yaw * 0.5;
	        var sinRoll = Math.sin(halfRoll);
	        var cosRoll = Math.cos(halfRoll);
	        var sinPitch = Math.sin(halfPitch);
	        var cosPitch = Math.cos(halfPitch);
	        var sinYaw = Math.sin(halfYaw);
	        var cosYaw = Math.cos(halfYaw);
	        var oe = out.elements;
	        oe[0] = (cosYaw * sinPitch * cosRoll) + (sinYaw * cosPitch * sinRoll);
	        oe[1] = (sinYaw * cosPitch * cosRoll) - (cosYaw * sinPitch * sinRoll);
	        oe[2] = (cosYaw * cosPitch * sinRoll) - (sinYaw * sinPitch * cosRoll);
	        oe[3] = (cosYaw * cosPitch * cosRoll) + (sinYaw * sinPitch * sinRoll);
	    }
	    static multiply(left, right, out) {
	        var le = left.elements;
	        var re = right.elements;
	        var oe = out.elements;
	        var lx = le[0];
	        var ly = le[1];
	        var lz = le[2];
	        var lw = le[3];
	        var rx = re[0];
	        var ry = re[1];
	        var rz = re[2];
	        var rw = re[3];
	        var a = (ly * rz - lz * ry);
	        var b = (lz * rx - lx * rz);
	        var c = (lx * ry - ly * rx);
	        var d = (lx * rx + ly * ry + lz * rz);
	        oe[0] = (lx * rw + rx * lw) + a;
	        oe[1] = (ly * rw + ry * lw) + b;
	        oe[2] = (lz * rw + rz * lw) + c;
	        oe[3] = lw * rw - d;
	    }
	    static arcTanAngle(x, y) {
	        if (x == 0) {
	            if (y == 1)
	                return Math.PI / 2;
	            return -Math.PI / 2;
	        }
	        if (x > 0)
	            return Math.atan(y / x);
	        if (x < 0) {
	            if (y > 0)
	                return Math.atan(y / x) + Math.PI;
	            return Math.atan(y / x) - Math.PI;
	        }
	        return 0;
	    }
	    static angleTo(from, location, angle) {
	        ConchVector3.subtract(location, from, ConchQuaternion.TEMPVector30);
	        ConchVector3.normalize(ConchQuaternion.TEMPVector30, ConchQuaternion.TEMPVector30);
	        angle.elements[0] = Math.asin(ConchQuaternion.TEMPVector30.y);
	        angle.elements[1] = ConchQuaternion.arcTanAngle(-ConchQuaternion.TEMPVector30.z, -ConchQuaternion.TEMPVector30.x);
	    }
	    static createFromAxisAngle(axis, rad, out) {
	        var e = out.elements;
	        var f = axis.elements;
	        rad = rad * 0.5;
	        var s = Math.sin(rad);
	        e[0] = s * f[0];
	        e[1] = s * f[1];
	        e[2] = s * f[2];
	        e[3] = Math.cos(rad);
	    }
	    static createFromMatrix3x3(sou, out) {
	        var e = out.elements;
	        var f = sou.elements;
	        var fTrace = f[0] + f[4] + f[8];
	        var fRoot;
	        if (fTrace > 0.0) {
	            fRoot = Math.sqrt(fTrace + 1.0);
	            e[3] = 0.5 * fRoot;
	            fRoot = 0.5 / fRoot;
	            e[0] = (f[5] - f[7]) * fRoot;
	            e[1] = (f[6] - f[2]) * fRoot;
	            e[2] = (f[1] - f[3]) * fRoot;
	        }
	        else {
	            var i = 0;
	            if (f[4] > f[0])
	                i = 1;
	            if (f[8] > f[i * 3 + i])
	                i = 2;
	            var j = (i + 1) % 3;
	            var k = (i + 2) % 3;
	            fRoot = Math.sqrt(f[i * 3 + i] - f[j * 3 + j] - f[k * 3 + k] + 1.0);
	            e[i] = 0.5 * fRoot;
	            fRoot = 0.5 / fRoot;
	            e[3] = (f[j * 3 + k] - f[k * 3 + j]) * fRoot;
	            e[j] = (f[j * 3 + i] + f[i * 3 + j]) * fRoot;
	            e[k] = (f[k * 3 + i] + f[i * 3 + k]) * fRoot;
	        }
	        return;
	    }
	    static createFromMatrix4x4(mat, out) {
	        var me = mat.elements;
	        var oe = out.elements;
	        var sqrt;
	        var half;
	        var scale = me[0] + me[5] + me[10];
	        if (scale > 0.0) {
	            sqrt = Math.sqrt(scale + 1.0);
	            oe[3] = sqrt * 0.5;
	            sqrt = 0.5 / sqrt;
	            oe[0] = (me[6] - me[9]) * sqrt;
	            oe[1] = (me[8] - me[2]) * sqrt;
	            oe[2] = (me[1] - me[4]) * sqrt;
	        }
	        else if ((me[0] >= me[5]) && (me[0] >= me[10])) {
	            sqrt = Math.sqrt(1.0 + me[0] - me[5] - me[10]);
	            half = 0.5 / sqrt;
	            oe[0] = 0.5 * sqrt;
	            oe[1] = (me[1] + me[4]) * half;
	            oe[2] = (me[2] + me[8]) * half;
	            oe[3] = (me[6] - me[9]) * half;
	        }
	        else if (me[5] > me[10]) {
	            sqrt = Math.sqrt(1.0 + me[5] - me[0] - me[10]);
	            half = 0.5 / sqrt;
	            oe[0] = (me[4] + me[1]) * half;
	            oe[1] = 0.5 * sqrt;
	            oe[2] = (me[9] + me[6]) * half;
	            oe[3] = (me[8] - me[2]) * half;
	        }
	        else {
	            sqrt = Math.sqrt(1.0 + me[10] - me[0] - me[5]);
	            half = 0.5 / sqrt;
	            oe[0] = (me[8] + me[2]) * half;
	            oe[1] = (me[9] + me[6]) * half;
	            oe[2] = 0.5 * sqrt;
	            oe[3] = (me[1] - me[4]) * half;
	        }
	    }
	    static slerp(left, right, t, out) {
	        var a = left.elements;
	        var b = right.elements;
	        var oe = out.elements;
	        var ax = a[0], ay = a[1], az = a[2], aw = a[3], bx = b[0], by = b[1], bz = b[2], bw = b[3];
	        var omega, cosom, sinom, scale0, scale1;
	        cosom = ax * bx + ay * by + az * bz + aw * bw;
	        if (cosom < 0.0) {
	            cosom = -cosom;
	            bx = -bx;
	            by = -by;
	            bz = -bz;
	            bw = -bw;
	        }
	        if ((1.0 - cosom) > 0.000001) {
	            omega = Math.acos(cosom);
	            sinom = Math.sin(omega);
	            scale0 = Math.sin((1.0 - t) * omega) / sinom;
	            scale1 = Math.sin(t * omega) / sinom;
	        }
	        else {
	            scale0 = 1.0 - t;
	            scale1 = t;
	        }
	        oe[0] = scale0 * ax + scale1 * bx;
	        oe[1] = scale0 * ay + scale1 * by;
	        oe[2] = scale0 * az + scale1 * bz;
	        oe[3] = scale0 * aw + scale1 * bw;
	        return oe;
	    }
	    static lerp(left, right, amount, out) {
	        ConchQuaternion._lerpArray(left.elements, right.elements, amount, out.elements);
	    }
	    static add(left, right, out) {
	        var e = out.elements;
	        var f = left.elements;
	        var g = right.elements;
	        e[0] = f[0] + g[0];
	        e[1] = f[1] + g[1];
	        e[2] = f[2] + g[2];
	        e[3] = f[3] + g[3];
	    }
	    static dot(left, right) {
	        return ConchQuaternion._dotArray(left.elements, right.elements);
	    }
	    get x() {
	        return this.elements[0];
	    }
	    set x(value) {
	        this.elements[0] = value;
	    }
	    get y() {
	        return this.elements[1];
	    }
	    set y(value) {
	        this.elements[1] = value;
	    }
	    get z() {
	        return this.elements[2];
	    }
	    set z(value) {
	        this.elements[2] = value;
	    }
	    get w() {
	        return this.elements[3];
	    }
	    set w(value) {
	        this.elements[3] = value;
	    }
	    scaling(scaling, out) {
	        var e = out.elements;
	        var f = this.elements;
	        e[0] = f[0] * scaling;
	        e[1] = f[1] * scaling;
	        e[2] = f[2] * scaling;
	        e[3] = f[3] * scaling;
	    }
	    normalize(out) {
	        ConchQuaternion._normalizeArray(this.elements, out.elements);
	    }
	    length() {
	        var f = this.elements;
	        var x = f[0], y = f[1], z = f[2], w = f[3];
	        return Math.sqrt(x * x + y * y + z * z + w * w);
	    }
	    rotateX(rad, out) {
	        var e = out.elements;
	        var f = this.elements;
	        rad *= 0.5;
	        var ax = f[0], ay = f[1], az = f[2], aw = f[3];
	        var bx = Math.sin(rad), bw = Math.cos(rad);
	        e[0] = ax * bw + aw * bx;
	        e[1] = ay * bw + az * bx;
	        e[2] = az * bw - ay * bx;
	        e[3] = aw * bw - ax * bx;
	    }
	    rotateY(rad, out) {
	        var e = out.elements;
	        var f = this.elements;
	        rad *= 0.5;
	        var ax = f[0], ay = f[1], az = f[2], aw = f[3], by = Math.sin(rad), bw = Math.cos(rad);
	        e[0] = ax * bw - az * by;
	        e[1] = ay * bw + aw * by;
	        e[2] = az * bw + ax * by;
	        e[3] = aw * bw - ay * by;
	    }
	    rotateZ(rad, out) {
	        var e = out.elements;
	        var f = this.elements;
	        rad *= 0.5;
	        var ax = f[0], ay = f[1], az = f[2], aw = f[3], bz = Math.sin(rad), bw = Math.cos(rad);
	        e[0] = ax * bw + ay * bz;
	        e[1] = ay * bw - ax * bz;
	        e[2] = az * bw + aw * bz;
	        e[3] = aw * bw - az * bz;
	    }
	    getYawPitchRoll(out) {
	        ConchVector3.transformQuat(ConchVector3.ForwardRH, this, ConchQuaternion.TEMPVector31);
	        ConchVector3.transformQuat(ConchVector3.Up, this, ConchQuaternion.TEMPVector32);
	        var upe = ConchQuaternion.TEMPVector32.elements;
	        ConchQuaternion.angleTo(ConchVector3.ZERO, ConchQuaternion.TEMPVector31, ConchQuaternion.TEMPVector33);
	        var anglee = ConchQuaternion.TEMPVector33.elements;
	        if (anglee[0] == Math.PI / 2) {
	            anglee[1] = ConchQuaternion.arcTanAngle(upe[2], upe[0]);
	            anglee[2] = 0;
	        }
	        else if (anglee[0] == -Math.PI / 2) {
	            anglee[1] = ConchQuaternion.arcTanAngle(-upe[2], -upe[0]);
	            anglee[2] = 0;
	        }
	        else {
	            Matrix4x4.createRotationY(-anglee[1], ConchQuaternion.TEMPMatrix0);
	            Matrix4x4.createRotationX(-anglee[0], ConchQuaternion.TEMPMatrix1);
	            ConchVector3.transformCoordinate(ConchQuaternion.TEMPVector32, ConchQuaternion.TEMPMatrix0, ConchQuaternion.TEMPVector32);
	            ConchVector3.transformCoordinate(ConchQuaternion.TEMPVector32, ConchQuaternion.TEMPMatrix1, ConchQuaternion.TEMPVector32);
	            anglee[2] = ConchQuaternion.arcTanAngle(upe[1], -upe[0]);
	        }
	        if (anglee[1] <= -Math.PI)
	            anglee[1] = Math.PI;
	        if (anglee[2] <= -Math.PI)
	            anglee[2] = Math.PI;
	        if (anglee[1] >= Math.PI && anglee[2] >= Math.PI) {
	            anglee[1] = 0;
	            anglee[2] = 0;
	            anglee[0] = Math.PI - anglee[0];
	        }
	        var oe = out.elements;
	        oe[0] = anglee[1];
	        oe[1] = anglee[0];
	        oe[2] = anglee[2];
	    }
	    invert(out) {
	        var e = out.elements;
	        var f = this.elements;
	        var a0 = f[0], a1 = f[1], a2 = f[2], a3 = f[3];
	        var dot = a0 * a0 + a1 * a1 + a2 * a2 + a3 * a3;
	        var invDot = dot ? 1.0 / dot : 0;
	        e[0] = -a0 * invDot;
	        e[1] = -a1 * invDot;
	        e[2] = -a2 * invDot;
	        e[3] = a3 * invDot;
	    }
	    identity() {
	        var e = this.elements;
	        e[0] = 0;
	        e[1] = 0;
	        e[2] = 0;
	        e[3] = 1;
	    }
	    fromArray(array, offset = 0) {
	        this.elements[0] = array[offset + 0];
	        this.elements[1] = array[offset + 1];
	        this.elements[2] = array[offset + 2];
	        this.elements[3] = array[offset + 3];
	    }
	    cloneTo(destObject) {
	        var i, s, d;
	        s = this.elements;
	        d = destObject.elements;
	        if (s === d) {
	            return;
	        }
	        for (i = 0; i < 4; ++i) {
	            d[i] = s[i];
	        }
	    }
	    clone() {
	        var dest = new ConchQuaternion();
	        this.cloneTo(dest);
	        return dest;
	    }
	    equals(b) {
	        var ae = this.elements;
	        var be = b.elements;
	        return MathUtils3D.nearEqual(ae[0], be[0]) && MathUtils3D.nearEqual(ae[1], be[1]) && MathUtils3D.nearEqual(ae[2], be[2]) && MathUtils3D.nearEqual(ae[3], be[3]);
	    }
	    static rotationLookAt(forward, up, out) {
	        ConchQuaternion.lookAt(ConchVector3.ZERO, forward, up, out);
	    }
	    static lookAt(eye, target, up, out) {
	        Matrix3x3.lookAt(eye, target, up, ConchQuaternion._tempMatrix3x3);
	        ConchQuaternion.rotationMatrix(ConchQuaternion._tempMatrix3x3, out);
	    }
	    lengthSquared() {
	        var x = this.elements[0];
	        var y = this.elements[1];
	        var z = this.elements[2];
	        var w = this.elements[3];
	        return (x * x) + (y * y) + (z * z) + (w * w);
	    }
	    static invert(value, out) {
	        var vE = value.elements;
	        var oE = out.elements;
	        var lengthSq = value.lengthSquared();
	        if (!MathUtils3D.isZero(lengthSq)) {
	            lengthSq = 1.0 / lengthSq;
	            oE[0] = -vE[0] * lengthSq;
	            oE[1] = -vE[1] * lengthSq;
	            oE[2] = -vE[2] * lengthSq;
	            oE[3] = vE[3] * lengthSq;
	        }
	    }
	    static rotationMatrix(matrix3x3, out) {
	        var me = matrix3x3.elements;
	        var m11 = me[0];
	        var m12 = me[1];
	        var m13 = me[2];
	        var m21 = me[3];
	        var m22 = me[4];
	        var m23 = me[5];
	        var m31 = me[6];
	        var m32 = me[7];
	        var m33 = me[8];
	        var oe = out.elements;
	        var sqrt, half;
	        var scale = m11 + m22 + m33;
	        if (scale > 0) {
	            sqrt = Math.sqrt(scale + 1);
	            oe[3] = sqrt * 0.5;
	            sqrt = 0.5 / sqrt;
	            oe[0] = (m23 - m32) * sqrt;
	            oe[1] = (m31 - m13) * sqrt;
	            oe[2] = (m12 - m21) * sqrt;
	        }
	        else if ((m11 >= m22) && (m11 >= m33)) {
	            sqrt = Math.sqrt(1 + m11 - m22 - m33);
	            half = 0.5 / sqrt;
	            oe[0] = 0.5 * sqrt;
	            oe[1] = (m12 + m21) * half;
	            oe[2] = (m13 + m31) * half;
	            oe[3] = (m23 - m32) * half;
	        }
	        else if (m22 > m33) {
	            sqrt = Math.sqrt(1 + m22 - m11 - m33);
	            half = 0.5 / sqrt;
	            oe[0] = (m21 + m12) * half;
	            oe[1] = 0.5 * sqrt;
	            oe[2] = (m32 + m23) * half;
	            oe[3] = (m31 - m13) * half;
	        }
	        else {
	            sqrt = Math.sqrt(1 + m33 - m11 - m22);
	            half = 0.5 / sqrt;
	            oe[0] = (m31 + m13) * half;
	            oe[1] = (m32 + m23) * half;
	            oe[2] = 0.5 * sqrt;
	            oe[3] = (m12 - m21) * half;
	        }
	    }
	}
	ConchQuaternion.TEMPVector30 = new ConchVector3();
	ConchQuaternion.TEMPVector31 = new ConchVector3();
	ConchQuaternion.TEMPVector32 = new ConchVector3();
	ConchQuaternion.TEMPVector33 = new ConchVector3();
	ConchQuaternion.TEMPMatrix0 = new Matrix4x4();
	ConchQuaternion.TEMPMatrix1 = new Matrix4x4();
	ConchQuaternion._tempMatrix3x3 = new Matrix3x3();
	ConchQuaternion.DEFAULT = new ConchQuaternion();
	ConchQuaternion.NAN = new ConchQuaternion(NaN, NaN, NaN, NaN);

	class AnimationClipParser03 {
	    static READ_DATA() {
	        AnimationClipParser03._DATA.offset = AnimationClipParser03._reader.getUint32();
	        AnimationClipParser03._DATA.size = AnimationClipParser03._reader.getUint32();
	    }
	    static READ_BLOCK() {
	        var count = AnimationClipParser03._BLOCK.count = AnimationClipParser03._reader.getUint16();
	        var blockStarts = AnimationClipParser03._BLOCK.blockStarts = [];
	        var blockLengths = AnimationClipParser03._BLOCK.blockLengths = [];
	        for (var i = 0; i < count; i++) {
	            blockStarts.push(AnimationClipParser03._reader.getUint32());
	            blockLengths.push(AnimationClipParser03._reader.getUint32());
	        }
	    }
	    static READ_STRINGS() {
	        var offset = AnimationClipParser03._reader.getUint32();
	        var count = AnimationClipParser03._reader.getUint16();
	        var prePos = AnimationClipParser03._reader.pos;
	        AnimationClipParser03._reader.pos = offset + AnimationClipParser03._DATA.offset;
	        for (var i = 0; i < count; i++)
	            AnimationClipParser03._strings[i] = AnimationClipParser03._reader.readUTFString();
	        AnimationClipParser03._reader.pos = prePos;
	    }
	    static parse(clip, reader) {
	        AnimationClipParser03._animationClip = clip;
	        AnimationClipParser03._reader = reader;
	        var arrayBuffer = reader.__getBuffer();
	        AnimationClipParser03.READ_DATA();
	        AnimationClipParser03.READ_BLOCK();
	        AnimationClipParser03.READ_STRINGS();
	        for (var i = 0, n = AnimationClipParser03._BLOCK.count; i < n; i++) {
	            var index = reader.getUint16();
	            var blockName = AnimationClipParser03._strings[index];
	            var fn = AnimationClipParser03["READ_" + blockName];
	            if (fn == null)
	                throw new Error("model file err,no this function:" + index + " " + blockName);
	            else
	                fn.call(null);
	        }
	    }
	    static READ_ANIMATIONS() {
	        var i, j;
	        var node;
	        var reader = AnimationClipParser03._reader;
	        var buffer = reader.__getBuffer();
	        var startTimeTypes = [];
	        var startTimeTypeCount = reader.getUint16();
	        startTimeTypes.length = startTimeTypeCount;
	        for (i = 0; i < startTimeTypeCount; i++)
	            startTimeTypes[i] = reader.getFloat32();
	        var clip = AnimationClipParser03._animationClip;
	        clip.name = AnimationClipParser03._strings[reader.getUint16()];
	        var clipDur = clip._duration = reader.getFloat32();
	        clip.islooping = !!reader.getByte();
	        clip._frameRate = reader.getInt16();
	        var nodeCount = reader.getInt16();
	        var nodes = clip._nodes;
	        nodes.count = nodeCount;
	        var nodesMap = clip._nodesMap = {};
	        var nodesDic = clip._nodesDic = {};
	        for (i = 0; i < nodeCount; i++) {
	            node = new KeyframeNode();
	            nodes.setNodeByIndex(i, node);
	            node._indexInList = i;
	            var type = node.type = reader.getUint8();
	            var pathLength = reader.getUint16();
	            node._setOwnerPathCount(pathLength);
	            for (j = 0; j < pathLength; j++)
	                node._setOwnerPathByIndex(j, AnimationClipParser03._strings[reader.getUint16()]);
	            var nodePath = node._joinOwnerPath("/");
	            var mapArray = nodesMap[nodePath];
	            (mapArray) || (nodesMap[nodePath] = mapArray = []);
	            mapArray.push(node);
	            node.propertyOwner = AnimationClipParser03._strings[reader.getUint16()];
	            var propertyLength = reader.getUint16();
	            node._setPropertyCount(propertyLength);
	            for (j = 0; j < propertyLength; j++)
	                node._setPropertyByIndex(j, AnimationClipParser03._strings[reader.getUint16()]);
	            var fullPath = nodePath + "." + node.propertyOwner + "." + node._joinProperty(".");
	            nodesDic[fullPath] = node;
	            node.fullPath = fullPath;
	            var keyframeCount = reader.getUint16();
	            node._setKeyframeCount(keyframeCount);
	            var startTime;
	            switch (type) {
	                case 0:
	                    break;
	                case 1:
	                case 3:
	                case 4:
	                    node.data = Laya.Render.supportWebGLPlusAnimation ? new ConchVector3 : new Vector3();
	                    break;
	                case 2:
	                    node.data = Laya.Render.supportWebGLPlusAnimation ? new ConchQuaternion : new Quaternion();
	                    break;
	                default:
	                    throw "AnimationClipParser03:unknown type.";
	            }
	            for (j = 0; j < keyframeCount; j++) {
	                switch (type) {
	                    case 0:
	                        var floatKeyframe = new FloatKeyframe();
	                        node._setKeyframeByIndex(j, floatKeyframe);
	                        startTime = floatKeyframe.time = startTimeTypes[reader.getUint16()];
	                        floatKeyframe.inTangent = reader.getFloat32();
	                        floatKeyframe.outTangent = reader.getFloat32();
	                        floatKeyframe.value = reader.getFloat32();
	                        break;
	                    case 1:
	                    case 3:
	                    case 4:
	                        var floatArrayKeyframe = new Vector3Keyframe();
	                        node._setKeyframeByIndex(j, floatArrayKeyframe);
	                        startTime = floatArrayKeyframe.time = startTimeTypes[reader.getUint16()];
	                        if (Laya.Render.supportWebGLPlusAnimation) {
	                            var data = floatArrayKeyframe.data = new Float32Array(3 * 3);
	                            for (var k = 0; k < 3; k++)
	                                data[k] = reader.getFloat32();
	                            for (k = 0; k < 3; k++)
	                                data[3 + k] = reader.getFloat32();
	                            for (k = 0; k < 3; k++)
	                                data[6 + k] = reader.getFloat32();
	                        }
	                        else {
	                            var inTangent = floatArrayKeyframe.inTangent;
	                            var outTangent = floatArrayKeyframe.outTangent;
	                            var value = floatArrayKeyframe.value;
	                            inTangent.x = reader.getFloat32();
	                            inTangent.y = reader.getFloat32();
	                            inTangent.z = reader.getFloat32();
	                            outTangent.x = reader.getFloat32();
	                            outTangent.y = reader.getFloat32();
	                            outTangent.z = reader.getFloat32();
	                            value.x = reader.getFloat32();
	                            value.y = reader.getFloat32();
	                            value.z = reader.getFloat32();
	                        }
	                        break;
	                    case 2:
	                        var quaArrayKeyframe = new QuaternionKeyframe();
	                        node._setKeyframeByIndex(j, quaArrayKeyframe);
	                        startTime = quaArrayKeyframe.time = startTimeTypes[reader.getUint16()];
	                        if (Laya.Render.supportWebGLPlusAnimation) {
	                            data = quaArrayKeyframe.data = new Float32Array(3 * 4);
	                            for (k = 0; k < 4; k++)
	                                data[k] = reader.getFloat32();
	                            for (k = 0; k < 4; k++)
	                                data[4 + k] = reader.getFloat32();
	                            for (k = 0; k < 4; k++)
	                                data[8 + k] = reader.getFloat32();
	                        }
	                        else {
	                            var inTangentQua = quaArrayKeyframe.inTangent;
	                            var outTangentQua = quaArrayKeyframe.outTangent;
	                            var valueQua = quaArrayKeyframe.value;
	                            inTangentQua.x = reader.getFloat32();
	                            inTangentQua.y = reader.getFloat32();
	                            inTangentQua.z = reader.getFloat32();
	                            inTangentQua.w = reader.getFloat32();
	                            outTangentQua.x = reader.getFloat32();
	                            outTangentQua.y = reader.getFloat32();
	                            outTangentQua.z = reader.getFloat32();
	                            outTangentQua.w = reader.getFloat32();
	                            valueQua.x = reader.getFloat32();
	                            valueQua.y = reader.getFloat32();
	                            valueQua.z = reader.getFloat32();
	                            valueQua.w = reader.getFloat32();
	                        }
	                        break;
	                    default:
	                        throw "AnimationClipParser03:unknown type.";
	                }
	            }
	        }
	        var eventCount = reader.getUint16();
	        for (i = 0; i < eventCount; i++) {
	            var event = new AnimationEvent();
	            event.time = Math.min(clipDur, reader.getFloat32());
	            event.eventName = AnimationClipParser03._strings[reader.getUint16()];
	            var params;
	            var paramCount = reader.getUint16();
	            (paramCount > 0) && (event.params = params = []);
	            for (j = 0; j < paramCount; j++) {
	                var eventType = reader.getByte();
	                switch (eventType) {
	                    case 0:
	                        params.push(!!reader.getByte());
	                        break;
	                    case 1:
	                        params.push(reader.getInt32());
	                        break;
	                    case 2:
	                        params.push(reader.getFloat32());
	                        break;
	                    case 3:
	                        params.push(AnimationClipParser03._strings[reader.getUint16()]);
	                        break;
	                    default:
	                        throw new Error("unknown type.");
	                }
	            }
	            clip.addEvent(event);
	        }
	    }
	}
	AnimationClipParser03._strings = [];
	AnimationClipParser03._BLOCK = { count: 0 };
	AnimationClipParser03._DATA = { offset: 0, size: 0 };

	class HalfFloatUtils {
	    static __init__() {
	        for (var i = 0; i < 256; ++i) {
	            var e = i - 127;
	            if (e < -27) {
	                HalfFloatUtils._baseTable[i | 0x000] = 0x0000;
	                HalfFloatUtils._baseTable[i | 0x100] = 0x8000;
	                HalfFloatUtils._shiftTable[i | 0x000] = 24;
	                HalfFloatUtils._shiftTable[i | 0x100] = 24;
	            }
	            else if (e < -14) {
	                HalfFloatUtils._baseTable[i | 0x000] = 0x0400 >> (-e - 14);
	                HalfFloatUtils._baseTable[i | 0x100] = (0x0400 >> (-e - 14)) | 0x8000;
	                HalfFloatUtils._shiftTable[i | 0x000] = -e - 1;
	                HalfFloatUtils._shiftTable[i | 0x100] = -e - 1;
	            }
	            else if (e <= 15) {
	                HalfFloatUtils._baseTable[i | 0x000] = (e + 15) << 10;
	                HalfFloatUtils._baseTable[i | 0x100] = ((e + 15) << 10) | 0x8000;
	                HalfFloatUtils._shiftTable[i | 0x000] = 13;
	                HalfFloatUtils._shiftTable[i | 0x100] = 13;
	            }
	            else if (e < 128) {
	                HalfFloatUtils._baseTable[i | 0x000] = 0x7c00;
	                HalfFloatUtils._baseTable[i | 0x100] = 0xfc00;
	                HalfFloatUtils._shiftTable[i | 0x000] = 24;
	                HalfFloatUtils._shiftTable[i | 0x100] = 24;
	            }
	            else {
	                HalfFloatUtils._baseTable[i | 0x000] = 0x7c00;
	                HalfFloatUtils._baseTable[i | 0x100] = 0xfc00;
	                HalfFloatUtils._shiftTable[i | 0x000] = 13;
	                HalfFloatUtils._shiftTable[i | 0x100] = 13;
	            }
	        }
	        HalfFloatUtils._mantissaTable[0] = 0;
	        for (i = 1; i < 1024; ++i) {
	            var m = i << 13;
	            e = 0;
	            while ((m & 0x00800000) === 0) {
	                e -= 0x00800000;
	                m <<= 1;
	            }
	            m &= ~0x00800000;
	            e += 0x38800000;
	            HalfFloatUtils._mantissaTable[i] = m | e;
	        }
	        for (i = 1024; i < 2048; ++i) {
	            HalfFloatUtils._mantissaTable[i] = 0x38000000 + ((i - 1024) << 13);
	        }
	        HalfFloatUtils._exponentTable[0] = 0;
	        for (i = 1; i < 31; ++i) {
	            HalfFloatUtils._exponentTable[i] = i << 23;
	        }
	        HalfFloatUtils._exponentTable[31] = 0x47800000;
	        HalfFloatUtils._exponentTable[32] = 0x80000000;
	        for (i = 33; i < 63; ++i) {
	            HalfFloatUtils._exponentTable[i] = 0x80000000 + ((i - 32) << 23);
	        }
	        HalfFloatUtils._exponentTable[63] = 0xc7800000;
	        HalfFloatUtils._offsetTable[0] = 0;
	        for (i = 1; i < 64; ++i) {
	            if (i === 32) {
	                HalfFloatUtils._offsetTable[i] = 0;
	            }
	            else {
	                HalfFloatUtils._offsetTable[i] = 1024;
	            }
	        }
	    }
	    static roundToFloat16Bits(num) {
	        HalfFloatUtils._floatView[0] = num;
	        var f = HalfFloatUtils._uint32View[0];
	        var e = (f >> 23) & 0x1ff;
	        return HalfFloatUtils._baseTable[e] + ((f & 0x007fffff) >> HalfFloatUtils._shiftTable[e]);
	    }
	    static convertToNumber(float16bits) {
	        var m = float16bits >> 10;
	        HalfFloatUtils._uint32View[0] = HalfFloatUtils._mantissaTable[HalfFloatUtils._offsetTable[m] + (float16bits & 0x3ff)] + HalfFloatUtils._exponentTable[m];
	        return HalfFloatUtils._floatView[0];
	    }
	}
	HalfFloatUtils._buffer = new ArrayBuffer(4);
	HalfFloatUtils._floatView = new Float32Array(HalfFloatUtils._buffer);
	HalfFloatUtils._uint32View = new Uint32Array(HalfFloatUtils._buffer);
	HalfFloatUtils._baseTable = new Uint32Array(512);
	HalfFloatUtils._shiftTable = new Uint32Array(512);
	HalfFloatUtils._mantissaTable = new Uint32Array(2048);
	HalfFloatUtils._exponentTable = new Uint32Array(64);
	HalfFloatUtils._offsetTable = new Uint32Array(64);

	class AnimationClipParser04 {
	    static READ_DATA() {
	        AnimationClipParser04._DATA.offset = AnimationClipParser04._reader.getUint32();
	        AnimationClipParser04._DATA.size = AnimationClipParser04._reader.getUint32();
	    }
	    static READ_BLOCK() {
	        var count = AnimationClipParser04._BLOCK.count = AnimationClipParser04._reader.getUint16();
	        var blockStarts = AnimationClipParser04._BLOCK.blockStarts = [];
	        var blockLengths = AnimationClipParser04._BLOCK.blockLengths = [];
	        for (var i = 0; i < count; i++) {
	            blockStarts.push(AnimationClipParser04._reader.getUint32());
	            blockLengths.push(AnimationClipParser04._reader.getUint32());
	        }
	    }
	    static READ_STRINGS() {
	        var offset = AnimationClipParser04._reader.getUint32();
	        var count = AnimationClipParser04._reader.getUint16();
	        var prePos = AnimationClipParser04._reader.pos;
	        AnimationClipParser04._reader.pos = offset + AnimationClipParser04._DATA.offset;
	        for (var i = 0; i < count; i++)
	            AnimationClipParser04._strings[i] = AnimationClipParser04._reader.readUTFString();
	        AnimationClipParser04._reader.pos = prePos;
	    }
	    static parse(clip, reader, version) {
	        AnimationClipParser04._animationClip = clip;
	        AnimationClipParser04._reader = reader;
	        AnimationClipParser04._version = version;
	        AnimationClipParser04.READ_DATA();
	        AnimationClipParser04.READ_BLOCK();
	        AnimationClipParser04.READ_STRINGS();
	        for (var i = 0, n = AnimationClipParser04._BLOCK.count; i < n; i++) {
	            var index = reader.getUint16();
	            var blockName = AnimationClipParser04._strings[index];
	            var fn = AnimationClipParser04["READ_" + blockName];
	            if (fn == null)
	                throw new Error("model file err,no this function:" + index + " " + blockName);
	            else
	                fn.call(null);
	        }
	        AnimationClipParser04._version = null;
	        AnimationClipParser04._reader = null;
	        AnimationClipParser04._animationClip = null;
	    }
	    static READ_ANIMATIONS() {
	        var i, j;
	        var node;
	        var reader = AnimationClipParser04._reader;
	        var buffer = reader.__getBuffer();
	        var startTimeTypes = [];
	        var startTimeTypeCount = reader.getUint16();
	        startTimeTypes.length = startTimeTypeCount;
	        for (i = 0; i < startTimeTypeCount; i++)
	            startTimeTypes[i] = reader.getFloat32();
	        var clip = AnimationClipParser04._animationClip;
	        clip.name = AnimationClipParser04._strings[reader.getUint16()];
	        var clipDur = clip._duration = reader.getFloat32();
	        clip.islooping = !!reader.getByte();
	        clip._frameRate = reader.getInt16();
	        var nodeCount = reader.getInt16();
	        var nodes = clip._nodes;
	        nodes.count = nodeCount;
	        var nodesMap = clip._nodesMap = {};
	        var nodesDic = clip._nodesDic = {};
	        for (i = 0; i < nodeCount; i++) {
	            node = new KeyframeNode();
	            nodes.setNodeByIndex(i, node);
	            node._indexInList = i;
	            var type = node.type = reader.getUint8();
	            var pathLength = reader.getUint16();
	            node._setOwnerPathCount(pathLength);
	            for (j = 0; j < pathLength; j++)
	                node._setOwnerPathByIndex(j, AnimationClipParser04._strings[reader.getUint16()]);
	            var nodePath = node._joinOwnerPath("/");
	            var mapArray = nodesMap[nodePath];
	            (mapArray) || (nodesMap[nodePath] = mapArray = []);
	            mapArray.push(node);
	            node.propertyOwner = AnimationClipParser04._strings[reader.getUint16()];
	            var propertyLength = reader.getUint16();
	            node._setPropertyCount(propertyLength);
	            for (j = 0; j < propertyLength; j++)
	                node._setPropertyByIndex(j, AnimationClipParser04._strings[reader.getUint16()]);
	            var fullPath = nodePath + "." + node.propertyOwner + "." + node._joinProperty(".");
	            nodesDic[fullPath] = node;
	            node.fullPath = fullPath;
	            var keyframeCount = reader.getUint16();
	            node._setKeyframeCount(keyframeCount);
	            var startTime;
	            switch (type) {
	                case 0:
	                    break;
	                case 1:
	                case 3:
	                case 4:
	                    node.data = Laya.Render.supportWebGLPlusAnimation ? new ConchVector3 : new Vector3();
	                    break;
	                case 2:
	                    node.data = Laya.Render.supportWebGLPlusAnimation ? new ConchQuaternion : new Quaternion();
	                    break;
	                default:
	                    throw "AnimationClipParser04:unknown type.";
	            }
	            switch (AnimationClipParser04._version) {
	                case "LAYAANIMATION:04":
	                    for (j = 0; j < keyframeCount; j++) {
	                        switch (type) {
	                            case 0:
	                                var floatKeyframe = new FloatKeyframe();
	                                node._setKeyframeByIndex(j, floatKeyframe);
	                                startTime = floatKeyframe.time = startTimeTypes[reader.getUint16()];
	                                floatKeyframe.inTangent = reader.getFloat32();
	                                floatKeyframe.outTangent = reader.getFloat32();
	                                floatKeyframe.value = reader.getFloat32();
	                                break;
	                            case 1:
	                            case 3:
	                            case 4:
	                                var floatArrayKeyframe = new Vector3Keyframe();
	                                node._setKeyframeByIndex(j, floatArrayKeyframe);
	                                startTime = floatArrayKeyframe.time = startTimeTypes[reader.getUint16()];
	                                if (Laya.Render.supportWebGLPlusAnimation) {
	                                    var data = floatArrayKeyframe.data = new Float32Array(3 * 3);
	                                    for (var k = 0; k < 3; k++)
	                                        data[k] = reader.getFloat32();
	                                    for (k = 0; k < 3; k++)
	                                        data[3 + k] = reader.getFloat32();
	                                    for (k = 0; k < 3; k++)
	                                        data[6 + k] = reader.getFloat32();
	                                }
	                                else {
	                                    var inTangent = floatArrayKeyframe.inTangent;
	                                    var outTangent = floatArrayKeyframe.outTangent;
	                                    var value = floatArrayKeyframe.value;
	                                    inTangent.x = reader.getFloat32();
	                                    inTangent.y = reader.getFloat32();
	                                    inTangent.z = reader.getFloat32();
	                                    outTangent.x = reader.getFloat32();
	                                    outTangent.y = reader.getFloat32();
	                                    outTangent.z = reader.getFloat32();
	                                    value.x = reader.getFloat32();
	                                    value.y = reader.getFloat32();
	                                    value.z = reader.getFloat32();
	                                }
	                                break;
	                            case 2:
	                                var quaternionKeyframe = new QuaternionKeyframe();
	                                node._setKeyframeByIndex(j, quaternionKeyframe);
	                                startTime = quaternionKeyframe.time = startTimeTypes[reader.getUint16()];
	                                if (Laya.Render.supportWebGLPlusAnimation) {
	                                    data = quaternionKeyframe.data = new Float32Array(3 * 4);
	                                    for (k = 0; k < 4; k++)
	                                        data[k] = reader.getFloat32();
	                                    for (k = 0; k < 4; k++)
	                                        data[4 + k] = reader.getFloat32();
	                                    for (k = 0; k < 4; k++)
	                                        data[8 + k] = reader.getFloat32();
	                                }
	                                else {
	                                    var inTangentQua = quaternionKeyframe.inTangent;
	                                    var outTangentQua = quaternionKeyframe.outTangent;
	                                    var valueQua = quaternionKeyframe.value;
	                                    inTangentQua.x = reader.getFloat32();
	                                    inTangentQua.y = reader.getFloat32();
	                                    inTangentQua.z = reader.getFloat32();
	                                    inTangentQua.w = reader.getFloat32();
	                                    outTangentQua.x = reader.getFloat32();
	                                    outTangentQua.y = reader.getFloat32();
	                                    outTangentQua.z = reader.getFloat32();
	                                    outTangentQua.w = reader.getFloat32();
	                                    valueQua.x = reader.getFloat32();
	                                    valueQua.y = reader.getFloat32();
	                                    valueQua.z = reader.getFloat32();
	                                    valueQua.w = reader.getFloat32();
	                                }
	                                break;
	                            default:
	                                throw "AnimationClipParser04:unknown type.";
	                        }
	                    }
	                    break;
	                case "LAYAANIMATION:COMPRESSION_04":
	                    for (j = 0; j < keyframeCount; j++) {
	                        switch (type) {
	                            case 0:
	                                floatKeyframe = new FloatKeyframe();
	                                node._setKeyframeByIndex(j, floatKeyframe);
	                                startTime = floatKeyframe.time = startTimeTypes[reader.getUint16()];
	                                floatKeyframe.inTangent = HalfFloatUtils.convertToNumber(reader.getUint16());
	                                floatKeyframe.outTangent = HalfFloatUtils.convertToNumber(reader.getUint16());
	                                floatKeyframe.value = HalfFloatUtils.convertToNumber(reader.getUint16());
	                                break;
	                            case 1:
	                            case 3:
	                            case 4:
	                                floatArrayKeyframe = new Vector3Keyframe();
	                                node._setKeyframeByIndex(j, floatArrayKeyframe);
	                                startTime = floatArrayKeyframe.time = startTimeTypes[reader.getUint16()];
	                                if (Laya.Render.supportWebGLPlusAnimation) {
	                                    data = floatArrayKeyframe.data = new Float32Array(3 * 3);
	                                    for (k = 0; k < 3; k++)
	                                        data[k] = HalfFloatUtils.convertToNumber(reader.getUint16());
	                                    for (k = 0; k < 3; k++)
	                                        data[3 + k] = HalfFloatUtils.convertToNumber(reader.getUint16());
	                                    for (k = 0; k < 3; k++)
	                                        data[6 + k] = HalfFloatUtils.convertToNumber(reader.getUint16());
	                                }
	                                else {
	                                    inTangent = floatArrayKeyframe.inTangent;
	                                    outTangent = floatArrayKeyframe.outTangent;
	                                    value = floatArrayKeyframe.value;
	                                    inTangent.x = HalfFloatUtils.convertToNumber(reader.getUint16());
	                                    inTangent.y = HalfFloatUtils.convertToNumber(reader.getUint16());
	                                    inTangent.z = HalfFloatUtils.convertToNumber(reader.getUint16());
	                                    outTangent.x = HalfFloatUtils.convertToNumber(reader.getUint16());
	                                    outTangent.y = HalfFloatUtils.convertToNumber(reader.getUint16());
	                                    outTangent.z = HalfFloatUtils.convertToNumber(reader.getUint16());
	                                    value.x = HalfFloatUtils.convertToNumber(reader.getUint16());
	                                    value.y = HalfFloatUtils.convertToNumber(reader.getUint16());
	                                    value.z = HalfFloatUtils.convertToNumber(reader.getUint16());
	                                }
	                                break;
	                            case 2:
	                                quaternionKeyframe = new QuaternionKeyframe();
	                                node._setKeyframeByIndex(j, quaternionKeyframe);
	                                startTime = quaternionKeyframe.time = startTimeTypes[reader.getUint16()];
	                                if (Laya.Render.supportWebGLPlusAnimation) {
	                                    data = quaternionKeyframe.data = new Float32Array(3 * 4);
	                                    for (k = 0; k < 4; k++)
	                                        data[k] = HalfFloatUtils.convertToNumber(reader.getUint16());
	                                    for (k = 0; k < 4; k++)
	                                        data[4 + k] = HalfFloatUtils.convertToNumber(reader.getUint16());
	                                    for (k = 0; k < 4; k++)
	                                        data[8 + k] = HalfFloatUtils.convertToNumber(reader.getUint16());
	                                }
	                                else {
	                                    inTangentQua = quaternionKeyframe.inTangent;
	                                    outTangentQua = quaternionKeyframe.outTangent;
	                                    valueQua = quaternionKeyframe.value;
	                                    inTangentQua.x = HalfFloatUtils.convertToNumber(reader.getUint16());
	                                    inTangentQua.y = HalfFloatUtils.convertToNumber(reader.getUint16());
	                                    inTangentQua.z = HalfFloatUtils.convertToNumber(reader.getUint16());
	                                    inTangentQua.w = HalfFloatUtils.convertToNumber(reader.getUint16());
	                                    outTangentQua.x = HalfFloatUtils.convertToNumber(reader.getUint16());
	                                    outTangentQua.y = HalfFloatUtils.convertToNumber(reader.getUint16());
	                                    outTangentQua.z = HalfFloatUtils.convertToNumber(reader.getUint16());
	                                    outTangentQua.w = HalfFloatUtils.convertToNumber(reader.getUint16());
	                                    valueQua.x = HalfFloatUtils.convertToNumber(reader.getUint16());
	                                    valueQua.y = HalfFloatUtils.convertToNumber(reader.getUint16());
	                                    valueQua.z = HalfFloatUtils.convertToNumber(reader.getUint16());
	                                    valueQua.w = HalfFloatUtils.convertToNumber(reader.getUint16());
	                                }
	                                break;
	                            default:
	                                throw "AnimationClipParser04:unknown type.";
	                        }
	                    }
	                    break;
	            }
	        }
	        var eventCount = reader.getUint16();
	        for (i = 0; i < eventCount; i++) {
	            var event = new AnimationEvent();
	            event.time = Math.min(clipDur, reader.getFloat32());
	            event.eventName = AnimationClipParser04._strings[reader.getUint16()];
	            var params;
	            var paramCount = reader.getUint16();
	            (paramCount > 0) && (event.params = params = []);
	            for (j = 0; j < paramCount; j++) {
	                var eventType = reader.getByte();
	                switch (eventType) {
	                    case 0:
	                        params.push(!!reader.getByte());
	                        break;
	                    case 1:
	                        params.push(reader.getInt32());
	                        break;
	                    case 2:
	                        params.push(reader.getFloat32());
	                        break;
	                    case 3:
	                        params.push(AnimationClipParser04._strings[reader.getUint16()]);
	                        break;
	                    default:
	                        throw new Error("unknown type.");
	                }
	            }
	            clip.addEvent(event);
	        }
	    }
	}
	AnimationClipParser04._strings = [];
	AnimationClipParser04._BLOCK = { count: 0 };
	AnimationClipParser04._DATA = { offset: 0, size: 0 };

	class KeyframeNodeList {
	    constructor() {
	        this._nodes = [];
	    }
	    get count() {
	        return this._nodes.length;
	    }
	    set count(value) {
	        this._nodes.length = value;
	    }
	    getNodeByIndex(index) {
	        return this._nodes[index];
	    }
	    setNodeByIndex(index, node) {
	        this._nodes[index] = node;
	    }
	}
	if (window.conch && window.conchKeyframeNodeList) {
	    KeyframeNodeList = window.conchKeyframeNodeList;
	}
	if (window.qq && window.qq.webglPlus) {
	    KeyframeNodeList = window.qq.webglPlus.conchKeyframeNodeList;
	}

	class TextureGenerator {
	    constructor() {
	    }
	    static lightAttenTexture(x, y, maxX, maxY, index, data) {
	        var sqrRange = x / maxX;
	        var atten = 1.0 / (1.0 + 25.0 * sqrRange);
	        if (sqrRange >= 0.64) {
	            if (sqrRange > 1.0) {
	                atten = 0;
	            }
	            else {
	                atten *= 1 - (sqrRange - 0.64) / (1 - 0.64);
	            }
	        }
	        data[index] = Math.floor(atten * 255.0 + 0.5);
	    }
	    static haloTexture(x, y, maxX, maxY, index, data) {
	        maxX >>= 1;
	        maxY >>= 1;
	        var xFac = (x - maxX) / maxX;
	        var yFac = (y - maxY) / maxY;
	        var sqrRange = xFac * xFac + yFac * yFac;
	        if (sqrRange > 1.0) {
	            sqrRange = 1.0;
	        }
	        data[index] = Math.floor((1.0 - sqrRange) * 255.0 + 0.5);
	    }
	    static _generateTexture2D(texture, textureWidth, textureHeight, func) {
	        var index = 0;
	        var size = 0;
	        switch (texture.format) {
	            case Laya.TextureFormat.R8G8B8:
	                size = 3;
	                break;
	            case Laya.TextureFormat.R8G8B8A8:
	                size = 4;
	                break;
	            case Laya.TextureFormat.Alpha8:
	                size = 1;
	                break;
	            default:
	                throw "GeneratedTexture._generateTexture: unkonw texture format.";
	        }
	        var data = new Uint8Array(textureWidth * textureHeight * size);
	        for (var y = 0; y < textureHeight; y++) {
	            for (var x = 0; x < textureWidth; x++) {
	                func(x, y, textureWidth, textureHeight, index, data);
	                index += size;
	            }
	        }
	        texture.setPixels(data);
	    }
	}

	class Utils3D {
	    static _createFloatTextureBuffer(width, height) {
	        var floatTex = new Laya.Texture2D(width, height, Laya.TextureFormat.R32G32B32A32, false, false);
	        floatTex.filterMode = Laya.BaseTexture.FILTERMODE_POINT;
	        floatTex.wrapModeU = Laya.BaseTexture.WARPMODE_CLAMP;
	        floatTex.wrapModeV = Laya.BaseTexture.WARPMODE_CLAMP;
	        floatTex.anisoLevel = 0;
	        return floatTex;
	    }
	    static _convertToLayaVec3(bVector, out, inverseX) {
	        out.x = inverseX ? -bVector.x() : bVector.x();
	        out.y = bVector.y();
	        out.z = bVector.z();
	    }
	    static _convertToBulletVec3(lVector, out, inverseX) {
	        out.setValue(inverseX ? -lVector.x : lVector.x, lVector.y, lVector.z);
	    }
	    static _rotationTransformScaleSkinAnimation(tx, ty, tz, qx, qy, qz, qw, sx, sy, sz, outArray, outOffset) {
	        var re = Utils3D._tempArray16_0;
	        var se = Utils3D._tempArray16_1;
	        var tse = Utils3D._tempArray16_2;
	        var x2 = qx + qx;
	        var y2 = qy + qy;
	        var z2 = qz + qz;
	        var xx = qx * x2;
	        var yx = qy * x2;
	        var yy = qy * y2;
	        var zx = qz * x2;
	        var zy = qz * y2;
	        var zz = qz * z2;
	        var wx = qw * x2;
	        var wy = qw * y2;
	        var wz = qw * z2;
	        re[15] = 1;
	        re[0] = 1 - yy - zz;
	        re[1] = yx + wz;
	        re[2] = zx - wy;
	        re[4] = yx - wz;
	        re[5] = 1 - xx - zz;
	        re[6] = zy + wx;
	        re[8] = zx + wy;
	        re[9] = zy - wx;
	        re[10] = 1 - xx - yy;
	        se[15] = 1;
	        se[0] = sx;
	        se[5] = sy;
	        se[10] = sz;
	        var i, ai0, ai1, ai2, ai3;
	        for (i = 0; i < 4; i++) {
	            ai0 = re[i];
	            ai1 = re[i + 4];
	            ai2 = re[i + 8];
	            ai3 = re[i + 12];
	            tse[i] = ai0;
	            tse[i + 4] = ai1;
	            tse[i + 8] = ai2;
	            tse[i + 12] = ai0 * tx + ai1 * ty + ai2 * tz + ai3;
	        }
	        for (i = 0; i < 4; i++) {
	            ai0 = tse[i];
	            ai1 = tse[i + 4];
	            ai2 = tse[i + 8];
	            ai3 = tse[i + 12];
	            outArray[i + outOffset] = ai0 * se[0] + ai1 * se[1] + ai2 * se[2] + ai3 * se[3];
	            outArray[i + outOffset + 4] = ai0 * se[4] + ai1 * se[5] + ai2 * se[6] + ai3 * se[7];
	            outArray[i + outOffset + 8] = ai0 * se[8] + ai1 * se[9] + ai2 * se[10] + ai3 * se[11];
	            outArray[i + outOffset + 12] = ai0 * se[12] + ai1 * se[13] + ai2 * se[14] + ai3 * se[15];
	        }
	    }
	    static _computeBoneAndAnimationDatasByBindPoseMatrxix(bones, curData, inverGlobalBindPose, outBonesDatas, outAnimationDatas, boneIndexToMesh) {
	        var offset = 0;
	        var matOffset = 0;
	        var i;
	        var parentOffset;
	        var boneLength = bones.length;
	        for (i = 0; i < boneLength; offset += bones[i].keyframeWidth, matOffset += 16, i++) {
	            Utils3D._rotationTransformScaleSkinAnimation(curData[offset + 0], curData[offset + 1], curData[offset + 2], curData[offset + 3], curData[offset + 4], curData[offset + 5], curData[offset + 6], curData[offset + 7], curData[offset + 8], curData[offset + 9], outBonesDatas, matOffset);
	            if (i != 0) {
	                parentOffset = bones[i].parentIndex * 16;
	                Utils3D.mulMatrixByArray(outBonesDatas, parentOffset, outBonesDatas, matOffset, outBonesDatas, matOffset);
	            }
	        }
	        var n = inverGlobalBindPose.length;
	        for (i = 0; i < n; i++) {
	            Utils3D.mulMatrixByArrayAndMatrixFast(outBonesDatas, boneIndexToMesh[i] * 16, inverGlobalBindPose[i], outAnimationDatas, i * 16);
	        }
	    }
	    static _computeAnimationDatasByArrayAndMatrixFast(inverGlobalBindPose, bonesDatas, outAnimationDatas, boneIndexToMesh) {
	        for (var i = 0, n = inverGlobalBindPose.length; i < n; i++)
	            Utils3D.mulMatrixByArrayAndMatrixFast(bonesDatas, boneIndexToMesh[i] * 16, inverGlobalBindPose[i], outAnimationDatas, i * 16);
	    }
	    static _computeBoneAndAnimationDatasByBindPoseMatrxixOld(bones, curData, inverGlobalBindPose, outBonesDatas, outAnimationDatas) {
	        var offset = 0;
	        var matOffset = 0;
	        var i;
	        var parentOffset;
	        var boneLength = bones.length;
	        for (i = 0; i < boneLength; offset += bones[i].keyframeWidth, matOffset += 16, i++) {
	            Utils3D._rotationTransformScaleSkinAnimation(curData[offset + 7], curData[offset + 8], curData[offset + 9], curData[offset + 3], curData[offset + 4], curData[offset + 5], curData[offset + 6], curData[offset + 0], curData[offset + 1], curData[offset + 2], outBonesDatas, matOffset);
	            if (i != 0) {
	                parentOffset = bones[i].parentIndex * 16;
	                Utils3D.mulMatrixByArray(outBonesDatas, parentOffset, outBonesDatas, matOffset, outBonesDatas, matOffset);
	            }
	        }
	        var n = inverGlobalBindPose.length;
	        for (i = 0; i < n; i++) {
	            var arrayOffset = i * 16;
	            Utils3D.mulMatrixByArrayAndMatrixFast(outBonesDatas, arrayOffset, inverGlobalBindPose[i], outAnimationDatas, arrayOffset);
	        }
	    }
	    static _computeAnimationDatasByArrayAndMatrixFastOld(inverGlobalBindPose, bonesDatas, outAnimationDatas) {
	        var n = inverGlobalBindPose.length;
	        for (var i = 0; i < n; i++) {
	            var arrayOffset = i * 16;
	            Utils3D.mulMatrixByArrayAndMatrixFast(bonesDatas, arrayOffset, inverGlobalBindPose[i], outAnimationDatas, arrayOffset);
	        }
	    }
	    static _computeRootAnimationData(bones, curData, animationDatas) {
	        for (var i = 0, offset = 0, matOffset = 0, boneLength = bones.length; i < boneLength; offset += bones[i].keyframeWidth, matOffset += 16, i++)
	            Utils3D.createAffineTransformationArray(curData[offset + 0], curData[offset + 1], curData[offset + 2], curData[offset + 3], curData[offset + 4], curData[offset + 5], curData[offset + 6], curData[offset + 7], curData[offset + 8], curData[offset + 9], animationDatas, matOffset);
	    }
	    static transformVector3ArrayByQuat(sourceArray, sourceOffset, rotation, outArray, outOffset) {
	        var x = sourceArray[sourceOffset], y = sourceArray[sourceOffset + 1], z = sourceArray[sourceOffset + 2], qx = rotation.x, qy = rotation.y, qz = rotation.z, qw = rotation.w, ix = qw * x + qy * z - qz * y, iy = qw * y + qz * x - qx * z, iz = qw * z + qx * y - qy * x, iw = -qx * x - qy * y - qz * z;
	        outArray[outOffset] = ix * qw + iw * -qx + iy * -qz - iz * -qy;
	        outArray[outOffset + 1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;
	        outArray[outOffset + 2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;
	    }
	    static mulMatrixByArray(leftArray, leftOffset, rightArray, rightOffset, outArray, outOffset) {
	        var i, ai0, ai1, ai2, ai3;
	        if (outArray === rightArray) {
	            rightArray = Utils3D._tempArray16_3;
	            for (i = 0; i < 16; ++i) {
	                rightArray[i] = outArray[outOffset + i];
	            }
	            rightOffset = 0;
	        }
	        for (i = 0; i < 4; i++) {
	            ai0 = leftArray[leftOffset + i];
	            ai1 = leftArray[leftOffset + i + 4];
	            ai2 = leftArray[leftOffset + i + 8];
	            ai3 = leftArray[leftOffset + i + 12];
	            outArray[outOffset + i] = ai0 * rightArray[rightOffset + 0] + ai1 * rightArray[rightOffset + 1] + ai2 * rightArray[rightOffset + 2] + ai3 * rightArray[rightOffset + 3];
	            outArray[outOffset + i + 4] = ai0 * rightArray[rightOffset + 4] + ai1 * rightArray[rightOffset + 5] + ai2 * rightArray[rightOffset + 6] + ai3 * rightArray[rightOffset + 7];
	            outArray[outOffset + i + 8] = ai0 * rightArray[rightOffset + 8] + ai1 * rightArray[rightOffset + 9] + ai2 * rightArray[rightOffset + 10] + ai3 * rightArray[rightOffset + 11];
	            outArray[outOffset + i + 12] = ai0 * rightArray[rightOffset + 12] + ai1 * rightArray[rightOffset + 13] + ai2 * rightArray[rightOffset + 14] + ai3 * rightArray[rightOffset + 15];
	        }
	    }
	    static mulMatrixByArrayFast(leftArray, leftOffset, rightArray, rightOffset, outArray, outOffset) {
	        var i, ai0, ai1, ai2, ai3;
	        for (i = 0; i < 4; i++) {
	            ai0 = leftArray[leftOffset + i];
	            ai1 = leftArray[leftOffset + i + 4];
	            ai2 = leftArray[leftOffset + i + 8];
	            ai3 = leftArray[leftOffset + i + 12];
	            outArray[outOffset + i] = ai0 * rightArray[rightOffset + 0] + ai1 * rightArray[rightOffset + 1] + ai2 * rightArray[rightOffset + 2] + ai3 * rightArray[rightOffset + 3];
	            outArray[outOffset + i + 4] = ai0 * rightArray[rightOffset + 4] + ai1 * rightArray[rightOffset + 5] + ai2 * rightArray[rightOffset + 6] + ai3 * rightArray[rightOffset + 7];
	            outArray[outOffset + i + 8] = ai0 * rightArray[rightOffset + 8] + ai1 * rightArray[rightOffset + 9] + ai2 * rightArray[rightOffset + 10] + ai3 * rightArray[rightOffset + 11];
	            outArray[outOffset + i + 12] = ai0 * rightArray[rightOffset + 12] + ai1 * rightArray[rightOffset + 13] + ai2 * rightArray[rightOffset + 14] + ai3 * rightArray[rightOffset + 15];
	        }
	    }
	    static mulMatrixByArrayAndMatrixFast(leftArray, leftOffset, rightMatrix, outArray, outOffset) {
	        var i, ai0, ai1, ai2, ai3;
	        var rightMatrixE = rightMatrix.elements;
	        var m11 = rightMatrixE[0], m12 = rightMatrixE[1], m13 = rightMatrixE[2], m14 = rightMatrixE[3];
	        var m21 = rightMatrixE[4], m22 = rightMatrixE[5], m23 = rightMatrixE[6], m24 = rightMatrixE[7];
	        var m31 = rightMatrixE[8], m32 = rightMatrixE[9], m33 = rightMatrixE[10], m34 = rightMatrixE[11];
	        var m41 = rightMatrixE[12], m42 = rightMatrixE[13], m43 = rightMatrixE[14], m44 = rightMatrixE[15];
	        var ai0LeftOffset = leftOffset;
	        var ai1LeftOffset = leftOffset + 4;
	        var ai2LeftOffset = leftOffset + 8;
	        var ai3LeftOffset = leftOffset + 12;
	        var ai0OutOffset = outOffset;
	        var ai1OutOffset = outOffset + 4;
	        var ai2OutOffset = outOffset + 8;
	        var ai3OutOffset = outOffset + 12;
	        for (i = 0; i < 4; i++) {
	            ai0 = leftArray[ai0LeftOffset + i];
	            ai1 = leftArray[ai1LeftOffset + i];
	            ai2 = leftArray[ai2LeftOffset + i];
	            ai3 = leftArray[ai3LeftOffset + i];
	            outArray[ai0OutOffset + i] = ai0 * m11 + ai1 * m12 + ai2 * m13 + ai3 * m14;
	            outArray[ai1OutOffset + i] = ai0 * m21 + ai1 * m22 + ai2 * m23 + ai3 * m24;
	            outArray[ai2OutOffset + i] = ai0 * m31 + ai1 * m32 + ai2 * m33 + ai3 * m34;
	            outArray[ai3OutOffset + i] = ai0 * m41 + ai1 * m42 + ai2 * m43 + ai3 * m44;
	        }
	    }
	    static createAffineTransformationArray(tX, tY, tZ, rX, rY, rZ, rW, sX, sY, sZ, outArray, outOffset) {
	        var x2 = rX + rX, y2 = rY + rY, z2 = rZ + rZ;
	        var xx = rX * x2, xy = rX * y2, xz = rX * z2, yy = rY * y2, yz = rY * z2, zz = rZ * z2;
	        var wx = rW * x2, wy = rW * y2, wz = rW * z2;
	        outArray[outOffset + 0] = (1 - (yy + zz)) * sX;
	        outArray[outOffset + 1] = (xy + wz) * sX;
	        outArray[outOffset + 2] = (xz - wy) * sX;
	        outArray[outOffset + 3] = 0;
	        outArray[outOffset + 4] = (xy - wz) * sY;
	        outArray[outOffset + 5] = (1 - (xx + zz)) * sY;
	        outArray[outOffset + 6] = (yz + wx) * sY;
	        outArray[outOffset + 7] = 0;
	        outArray[outOffset + 8] = (xz + wy) * sZ;
	        outArray[outOffset + 9] = (yz - wx) * sZ;
	        outArray[outOffset + 10] = (1 - (xx + yy)) * sZ;
	        outArray[outOffset + 11] = 0;
	        outArray[outOffset + 12] = tX;
	        outArray[outOffset + 13] = tY;
	        outArray[outOffset + 14] = tZ;
	        outArray[outOffset + 15] = 1;
	    }
	    static transformVector3ArrayToVector3ArrayCoordinate(source, sourceOffset, transform, result, resultOffset) {
	        var coordinateX = source[sourceOffset + 0];
	        var coordinateY = source[sourceOffset + 1];
	        var coordinateZ = source[sourceOffset + 2];
	        var transformElem = transform.elements;
	        var w = ((coordinateX * transformElem[3]) + (coordinateY * transformElem[7]) + (coordinateZ * transformElem[11]) + transformElem[15]);
	        result[resultOffset] = (coordinateX * transformElem[0]) + (coordinateY * transformElem[4]) + (coordinateZ * transformElem[8]) + transformElem[12] / w;
	        result[resultOffset + 1] = (coordinateX * transformElem[1]) + (coordinateY * transformElem[5]) + (coordinateZ * transformElem[9]) + transformElem[13] / w;
	        result[resultOffset + 2] = (coordinateX * transformElem[2]) + (coordinateY * transformElem[6]) + (coordinateZ * transformElem[10]) + transformElem[14] / w;
	    }
	    static transformLightingMapTexcoordArray(source, sourceOffset, lightingMapScaleOffset, result, resultOffset) {
	        result[resultOffset + 0] = source[sourceOffset + 0] * lightingMapScaleOffset.x + lightingMapScaleOffset.z;
	        result[resultOffset + 1] = 1.0 - ((1.0 - source[sourceOffset + 1]) * lightingMapScaleOffset.y + lightingMapScaleOffset.w);
	    }
	    static getURLVerion(url) {
	        var index = url.indexOf("?");
	        return index >= 0 ? url.substr(index) : null;
	    }
	    static _createAffineTransformationArray(trans, rot, scale, outE) {
	        var x = rot.x, y = rot.y, z = rot.z, w = rot.w, x2 = x + x, y2 = y + y, z2 = z + z;
	        var xx = x * x2, xy = x * y2, xz = x * z2, yy = y * y2, yz = y * z2, zz = z * z2;
	        var wx = w * x2, wy = w * y2, wz = w * z2, sx = scale.x, sy = scale.y, sz = scale.z;
	        outE[0] = (1 - (yy + zz)) * sx;
	        outE[1] = (xy + wz) * sx;
	        outE[2] = (xz - wy) * sx;
	        outE[3] = 0;
	        outE[4] = (xy - wz) * sy;
	        outE[5] = (1 - (xx + zz)) * sy;
	        outE[6] = (yz + wx) * sy;
	        outE[7] = 0;
	        outE[8] = (xz + wy) * sz;
	        outE[9] = (yz - wx) * sz;
	        outE[10] = (1 - (xx + yy)) * sz;
	        outE[11] = 0;
	        outE[12] = trans.x;
	        outE[13] = trans.y;
	        outE[14] = trans.z;
	        outE[15] = 1;
	    }
	    static _mulMatrixArray(leftMatrixE, rightMatrix, outArray, outOffset) {
	        var i, ai0, ai1, ai2, ai3;
	        var rightMatrixE = rightMatrix.elements;
	        var m11 = rightMatrixE[0], m12 = rightMatrixE[1], m13 = rightMatrixE[2], m14 = rightMatrixE[3];
	        var m21 = rightMatrixE[4], m22 = rightMatrixE[5], m23 = rightMatrixE[6], m24 = rightMatrixE[7];
	        var m31 = rightMatrixE[8], m32 = rightMatrixE[9], m33 = rightMatrixE[10], m34 = rightMatrixE[11];
	        var m41 = rightMatrixE[12], m42 = rightMatrixE[13], m43 = rightMatrixE[14], m44 = rightMatrixE[15];
	        var ai0OutOffset = outOffset;
	        var ai1OutOffset = outOffset + 4;
	        var ai2OutOffset = outOffset + 8;
	        var ai3OutOffset = outOffset + 12;
	        for (i = 0; i < 4; i++) {
	            ai0 = leftMatrixE[i];
	            ai1 = leftMatrixE[i + 4];
	            ai2 = leftMatrixE[i + 8];
	            ai3 = leftMatrixE[i + 12];
	            outArray[ai0OutOffset + i] = ai0 * m11 + ai1 * m12 + ai2 * m13 + ai3 * m14;
	            outArray[ai1OutOffset + i] = ai0 * m21 + ai1 * m22 + ai2 * m23 + ai3 * m24;
	            outArray[ai2OutOffset + i] = ai0 * m31 + ai1 * m32 + ai2 * m33 + ai3 * m34;
	            outArray[ai3OutOffset + i] = ai0 * m41 + ai1 * m42 + ai2 * m43 + ai3 * m44;
	        }
	    }
	    static arcTanAngle(x, y) {
	        if (x == 0) {
	            if (y == 1)
	                return Math.PI / 2;
	            return -Math.PI / 2;
	        }
	        if (x > 0)
	            return Math.atan(y / x);
	        if (x < 0) {
	            if (y > 0)
	                return Math.atan(y / x) + Math.PI;
	            return Math.atan(y / x) - Math.PI;
	        }
	        return 0;
	    }
	    static angleTo(from, location, angle) {
	        Vector3.subtract(location, from, Quaternion.TEMPVector30);
	        Vector3.normalize(Quaternion.TEMPVector30, Quaternion.TEMPVector30);
	        angle.x = Math.asin(Quaternion.TEMPVector30.y);
	        angle.y = Utils3D.arcTanAngle(-Quaternion.TEMPVector30.z, -Quaternion.TEMPVector30.x);
	    }
	    static transformQuat(source, rotation, out) {
	        var re = rotation;
	        var x = source.x, y = source.y, z = source.z, qx = re[0], qy = re[1], qz = re[2], qw = re[3], ix = qw * x + qy * z - qz * y, iy = qw * y + qz * x - qx * z, iz = qw * z + qx * y - qy * x, iw = -qx * x - qy * y - qz * z;
	        out.x = ix * qw + iw * -qx + iy * -qz - iz * -qy;
	        out.y = iy * qw + iw * -qy + iz * -qx - ix * -qz;
	        out.z = iz * qw + iw * -qz + ix * -qy - iy * -qx;
	    }
	    static quaternionWeight(f, weight, e) {
	        e.x = f.x * weight;
	        e.y = f.y * weight;
	        e.z = f.z * weight;
	        e.w = f.w;
	    }
	    static quaternionConjugate(value, result) {
	        result.x = -value.x;
	        result.y = -value.y;
	        result.z = -value.z;
	        result.w = value.w;
	    }
	    static scaleWeight(s, w, out) {
	        var sX = s.x, sY = s.y, sZ = s.z;
	        out.x = sX > 0 ? Math.pow(Math.abs(sX), w) : -Math.pow(Math.abs(sX), w);
	        out.y = sY > 0 ? Math.pow(Math.abs(sY), w) : -Math.pow(Math.abs(sY), w);
	        out.z = sZ > 0 ? Math.pow(Math.abs(sZ), w) : -Math.pow(Math.abs(sZ), w);
	    }
	    static scaleBlend(sa, sb, w, out) {
	        var saw = Utils3D._tempVector3_0;
	        var sbw = Utils3D._tempVector3_1;
	        Utils3D.scaleWeight(sa, 1.0 - w, saw);
	        Utils3D.scaleWeight(sb, w, sbw);
	        var sng = w > 0.5 ? sb : sa;
	        out.x = sng.x > 0 ? Math.abs(saw.x * sbw.x) : -Math.abs(saw.x * sbw.x);
	        out.y = sng.y > 0 ? Math.abs(saw.y * sbw.y) : -Math.abs(saw.y * sbw.y);
	        out.z = sng.z > 0 ? Math.abs(saw.z * sbw.z) : -Math.abs(saw.z * sbw.z);
	    }
	    static matrix4x4MultiplyFFF(a, b, e) {
	        var i, ai0, ai1, ai2, ai3;
	        if (e === b) {
	            b = new Float32Array(16);
	            for (i = 0; i < 16; ++i) {
	                b[i] = e[i];
	            }
	        }
	        var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3];
	        var b4 = b[4], b5 = b[5], b6 = b[6], b7 = b[7];
	        var b8 = b[8], b9 = b[9], b10 = b[10], b11 = b[11];
	        var b12 = b[12], b13 = b[13], b14 = b[14], b15 = b[15];
	        for (i = 0; i < 4; i++) {
	            ai0 = a[i];
	            ai1 = a[i + 4];
	            ai2 = a[i + 8];
	            ai3 = a[i + 12];
	            e[i] = ai0 * b0 + ai1 * b1 + ai2 * b2 + ai3 * b3;
	            e[i + 4] = ai0 * b4 + ai1 * b5 + ai2 * b6 + ai3 * b7;
	            e[i + 8] = ai0 * b8 + ai1 * b9 + ai2 * b10 + ai3 * b11;
	            e[i + 12] = ai0 * b12 + ai1 * b13 + ai2 * b14 + ai3 * b15;
	        }
	    }
	    static matrix4x4MultiplyFFFForNative(a, b, e) {
	        Laya.LayaGL.instance.matrix4x4Multiply(a, b, e);
	    }
	    static matrix4x4MultiplyMFM(left, right, out) {
	        Utils3D.matrix4x4MultiplyFFF(left.elements, right, out.elements);
	    }
	    static _buildTexture2D(width, height, format, colorFunc, mipmaps = false) {
	        var texture = new Laya.Texture2D(width, height, format, mipmaps, true);
	        texture.anisoLevel = 1;
	        texture.filterMode = Laya.BaseTexture.FILTERMODE_POINT;
	        TextureGenerator._generateTexture2D(texture, width, height, colorFunc);
	        return texture;
	    }
	    static _drawBound(debugLine, boundBox, color) {
	        if (debugLine.lineCount + 12 > debugLine.maxLineCount)
	            debugLine.maxLineCount += 12;
	        var start = Utils3D._tempVector3_0;
	        var end = Utils3D._tempVector3_1;
	        var min = boundBox.min;
	        var max = boundBox.max;
	        start.setValue(min.x, min.y, min.z);
	        end.setValue(max.x, min.y, min.z);
	        debugLine.addLine(start, end, color, color);
	        start.setValue(min.x, min.y, min.z);
	        end.setValue(min.x, min.y, max.z);
	        debugLine.addLine(start, end, color, color);
	        start.setValue(max.x, min.y, min.z);
	        end.setValue(max.x, min.y, max.z);
	        debugLine.addLine(start, end, color, color);
	        start.setValue(min.x, min.y, max.z);
	        end.setValue(max.x, min.y, max.z);
	        debugLine.addLine(start, end, color, color);
	        start.setValue(min.x, min.y, min.z);
	        end.setValue(min.x, max.y, min.z);
	        debugLine.addLine(start, end, color, color);
	        start.setValue(min.x, min.y, max.z);
	        end.setValue(min.x, max.y, max.z);
	        debugLine.addLine(start, end, color, color);
	        start.setValue(max.x, min.y, min.z);
	        end.setValue(max.x, max.y, min.z);
	        debugLine.addLine(start, end, color, color);
	        start.setValue(max.x, min.y, max.z);
	        end.setValue(max.x, max.y, max.z);
	        debugLine.addLine(start, end, color, color);
	        start.setValue(min.x, max.y, min.z);
	        end.setValue(max.x, max.y, min.z);
	        debugLine.addLine(start, end, color, color);
	        start.setValue(min.x, max.y, min.z);
	        end.setValue(min.x, max.y, max.z);
	        debugLine.addLine(start, end, color, color);
	        start.setValue(max.x, max.y, min.z);
	        end.setValue(max.x, max.y, max.z);
	        debugLine.addLine(start, end, color, color);
	        start.setValue(min.x, max.y, max.z);
	        end.setValue(max.x, max.y, max.z);
	        debugLine.addLine(start, end, color, color);
	    }
	    static _getHierarchyPath(rootSprite, checkSprite, path) {
	        path.length = 0;
	        var sprite = checkSprite;
	        while (sprite !== rootSprite) {
	            var parent = sprite._parent;
	            if (parent)
	                path.push(parent.getChildIndex(sprite));
	            else
	                return null;
	            sprite = parent;
	        }
	        return path;
	    }
	    static _getNodeByHierarchyPath(rootSprite, invPath) {
	        var sprite = rootSprite;
	        for (var i = invPath.length - 1; i >= 0; i--) {
	            sprite = sprite.getChildAt(invPath[i]);
	        }
	        return sprite;
	    }
	}
	Utils3D._tempVector3_0 = new Vector3();
	Utils3D._tempVector3_1 = new Vector3();
	Utils3D._tempArray16_0 = new Float32Array(16);
	Utils3D._tempArray16_1 = new Float32Array(16);
	Utils3D._tempArray16_2 = new Float32Array(16);
	Utils3D._tempArray16_3 = new Float32Array(16);
	Utils3D._compIdToNode = new Object();

	class AnimationClip extends Laya.Resource {
	    constructor() {
	        super();
	        this._nodes = new KeyframeNodeList();
	        this._animationEvents = [];
	    }
	    static _parse(data, propertyParams = null, constructParams = null) {
	        var clip = new AnimationClip();
	        var reader = new Laya.Byte(data);
	        var version = reader.readUTFString();
	        switch (version) {
	            case "LAYAANIMATION:03":
	                AnimationClipParser03.parse(clip, reader);
	                break;
	            case "LAYAANIMATION:04":
	            case "LAYAANIMATION:COMPRESSION_04":
	                AnimationClipParser04.parse(clip, reader, version);
	                break;
	            default:
	                throw "unknown animationClip version.";
	        }
	        return clip;
	    }
	    static load(url, complete) {
	        Laya.ILaya.loader.create(url, complete, null, AnimationClip.ANIMATIONCLIP);
	    }
	    duration() {
	        return this._duration;
	    }
	    _hermiteInterpolate(frame, nextFrame, t, dur) {
	        var t0 = frame.outTangent, t1 = nextFrame.inTangent;
	        if (Number.isFinite(t0) && Number.isFinite(t1)) {
	            var t2 = t * t;
	            var t3 = t2 * t;
	            var a = 2.0 * t3 - 3.0 * t2 + 1.0;
	            var b = t3 - 2.0 * t2 + t;
	            var c = t3 - t2;
	            var d = -2.0 * t3 + 3.0 * t2;
	            return a * frame.value + b * t0 * dur + c * t1 * dur + d * nextFrame.value;
	        }
	        else
	            return frame.value;
	    }
	    _hermiteInterpolateVector3(frame, nextFrame, t, dur, out) {
	        var p0 = frame.value;
	        var tan0 = frame.outTangent;
	        var p1 = nextFrame.value;
	        var tan1 = nextFrame.inTangent;
	        var t2 = t * t;
	        var t3 = t2 * t;
	        var a = 2.0 * t3 - 3.0 * t2 + 1.0;
	        var b = t3 - 2.0 * t2 + t;
	        var c = t3 - t2;
	        var d = -2.0 * t3 + 3.0 * t2;
	        var t0 = tan0.x, t1 = tan1.x;
	        if (Number.isFinite(t0) && Number.isFinite(t1))
	            out.x = a * p0.x + b * t0 * dur + c * t1 * dur + d * p1.x;
	        else
	            out.x = p0.x;
	        t0 = tan0.y, t1 = tan1.y;
	        if (Number.isFinite(t0) && Number.isFinite(t1))
	            out.y = a * p0.y + b * t0 * dur + c * t1 * dur + d * p1.y;
	        else
	            out.y = p0.y;
	        t0 = tan0.z, t1 = tan1.z;
	        if (Number.isFinite(t0) && Number.isFinite(t1))
	            out.z = a * p0.z + b * t0 * dur + c * t1 * dur + d * p1.z;
	        else
	            out.z = p0.z;
	    }
	    _hermiteInterpolateQuaternion(frame, nextFrame, t, dur, out) {
	        var p0 = frame.value;
	        var tan0 = frame.outTangent;
	        var p1 = nextFrame.value;
	        var tan1 = nextFrame.inTangent;
	        var t2 = t * t;
	        var t3 = t2 * t;
	        var a = 2.0 * t3 - 3.0 * t2 + 1.0;
	        var b = t3 - 2.0 * t2 + t;
	        var c = t3 - t2;
	        var d = -2.0 * t3 + 3.0 * t2;
	        var t0 = tan0.x, t1 = tan1.x;
	        if (Number.isFinite(t0) && Number.isFinite(t1))
	            out.x = a * p0.x + b * t0 * dur + c * t1 * dur + d * p1.x;
	        else
	            out.x = p0.x;
	        t0 = tan0.y, t1 = tan1.y;
	        if (Number.isFinite(t0) && Number.isFinite(t1))
	            out.y = a * p0.y + b * t0 * dur + c * t1 * dur + d * p1.y;
	        else
	            out.y = p0.y;
	        t0 = tan0.z, t1 = tan1.z;
	        if (Number.isFinite(t0) && Number.isFinite(t1))
	            out.z = a * p0.z + b * t0 * dur + c * t1 * dur + d * p1.z;
	        else
	            out.z = p0.z;
	        t0 = tan0.w, t1 = tan1.w;
	        if (Number.isFinite(t0) && Number.isFinite(t1))
	            out.w = a * p0.w + b * t0 * dur + c * t1 * dur + d * p1.w;
	        else
	            out.w = p0.w;
	    }
	    _evaluateClipDatasRealTime(nodes, playCurTime, realTimeCurrentFrameIndexes, addtive, frontPlay) {
	        for (var i = 0, n = nodes.count; i < n; i++) {
	            var node = nodes.getNodeByIndex(i);
	            var type = node.type;
	            var nextFrameIndex;
	            var keyFrames = node._keyFrames;
	            var keyFramesCount = keyFrames.length;
	            var frameIndex = realTimeCurrentFrameIndexes[i];
	            if (frontPlay) {
	                if ((frameIndex !== -1) && (playCurTime < keyFrames[frameIndex].time)) {
	                    frameIndex = -1;
	                    realTimeCurrentFrameIndexes[i] = frameIndex;
	                }
	                nextFrameIndex = frameIndex + 1;
	                while (nextFrameIndex < keyFramesCount) {
	                    if (keyFrames[nextFrameIndex].time > playCurTime)
	                        break;
	                    frameIndex++;
	                    nextFrameIndex++;
	                    realTimeCurrentFrameIndexes[i] = frameIndex;
	                }
	            }
	            else {
	                nextFrameIndex = frameIndex + 1;
	                if ((nextFrameIndex !== keyFramesCount) && (playCurTime > keyFrames[nextFrameIndex].time)) {
	                    frameIndex = keyFramesCount - 1;
	                    realTimeCurrentFrameIndexes[i] = frameIndex;
	                }
	                nextFrameIndex = frameIndex + 1;
	                while (frameIndex > -1) {
	                    if (keyFrames[frameIndex].time < playCurTime)
	                        break;
	                    frameIndex--;
	                    nextFrameIndex--;
	                    realTimeCurrentFrameIndexes[i] = frameIndex;
	                }
	            }
	            var isEnd = nextFrameIndex === keyFramesCount;
	            switch (type) {
	                case 0:
	                    if (frameIndex !== -1) {
	                        var frame = keyFrames[frameIndex];
	                        if (isEnd) {
	                            node.data = frame.value;
	                        }
	                        else {
	                            var nextFarme = keyFrames[nextFrameIndex];
	                            var d = nextFarme.time - frame.time;
	                            var t;
	                            if (d !== 0)
	                                t = (playCurTime - frame.time) / d;
	                            else
	                                t = 0;
	                            node.data = this._hermiteInterpolate(frame, nextFarme, t, d);
	                        }
	                    }
	                    else {
	                        node.data = keyFrames[0].value;
	                    }
	                    if (addtive)
	                        node.data -= keyFrames[0].value;
	                    break;
	                case 1:
	                case 4:
	                    var clipData = node.data;
	                    this._evaluateFrameNodeVector3DatasRealTime(keyFrames, frameIndex, isEnd, playCurTime, clipData);
	                    if (addtive) {
	                        var firstFrameValue = keyFrames[0].value;
	                        clipData.x -= firstFrameValue.x;
	                        clipData.y -= firstFrameValue.y;
	                        clipData.z -= firstFrameValue.z;
	                    }
	                    break;
	                case 2:
	                    var clipQuat = node.data;
	                    this._evaluateFrameNodeQuaternionDatasRealTime(keyFrames, frameIndex, isEnd, playCurTime, clipQuat);
	                    if (addtive) {
	                        var tempQuat = AnimationClip._tempQuaternion0;
	                        var firstFrameValueQua = keyFrames[0].value;
	                        Utils3D.quaternionConjugate(firstFrameValueQua, tempQuat);
	                        Quaternion.multiply(tempQuat, clipQuat, clipQuat);
	                    }
	                    break;
	                case 3:
	                    clipData = node.data;
	                    this._evaluateFrameNodeVector3DatasRealTime(keyFrames, frameIndex, isEnd, playCurTime, clipData);
	                    if (addtive) {
	                        firstFrameValue = keyFrames[0].value;
	                        clipData.x /= firstFrameValue.x;
	                        clipData.y /= firstFrameValue.y;
	                        clipData.z /= firstFrameValue.z;
	                    }
	                    break;
	                default:
	                    throw "AnimationClip:unknown node type.";
	            }
	        }
	    }
	    _evaluateClipDatasRealTimeForNative(nodes, playCurTime, realTimeCurrentFrameIndexes, addtive) {
	        Laya.LayaGL.instance.evaluateClipDatasRealTime(nodes._nativeObj, playCurTime, realTimeCurrentFrameIndexes, addtive);
	    }
	    _evaluateFrameNodeVector3DatasRealTime(keyFrames, frameIndex, isEnd, playCurTime, outDatas) {
	        if (frameIndex !== -1) {
	            var frame = keyFrames[frameIndex];
	            if (isEnd) {
	                var frameData = frame.value;
	                outDatas.x = frameData.x;
	                outDatas.y = frameData.y;
	                outDatas.z = frameData.z;
	            }
	            else {
	                var nextKeyFrame = keyFrames[frameIndex + 1];
	                var t;
	                var startTime = frame.time;
	                var d = nextKeyFrame.time - startTime;
	                if (d !== 0)
	                    t = (playCurTime - startTime) / d;
	                else
	                    t = 0;
	                this._hermiteInterpolateVector3(frame, nextKeyFrame, t, d, outDatas);
	            }
	        }
	        else {
	            var firstFrameDatas = keyFrames[0].value;
	            outDatas.x = firstFrameDatas.x;
	            outDatas.y = firstFrameDatas.y;
	            outDatas.z = firstFrameDatas.z;
	        }
	    }
	    _evaluateFrameNodeQuaternionDatasRealTime(keyFrames, frameIndex, isEnd, playCurTime, outDatas) {
	        if (frameIndex !== -1) {
	            var frame = keyFrames[frameIndex];
	            if (isEnd) {
	                var frameData = frame.value;
	                outDatas.x = frameData.x;
	                outDatas.y = frameData.y;
	                outDatas.z = frameData.z;
	                outDatas.w = frameData.w;
	            }
	            else {
	                var nextKeyFrame = keyFrames[frameIndex + 1];
	                var t;
	                var startTime = frame.time;
	                var d = nextKeyFrame.time - startTime;
	                if (d !== 0)
	                    t = (playCurTime - startTime) / d;
	                else
	                    t = 0;
	                this._hermiteInterpolateQuaternion(frame, nextKeyFrame, t, d, outDatas);
	            }
	        }
	        else {
	            var firstFrameDatas = keyFrames[0].value;
	            outDatas.x = firstFrameDatas.x;
	            outDatas.y = firstFrameDatas.y;
	            outDatas.z = firstFrameDatas.z;
	            outDatas.w = firstFrameDatas.w;
	        }
	    }
	    _binarySearchEventIndex(time) {
	        var start = 0;
	        var end = this._animationEvents.length - 1;
	        var mid;
	        while (start <= end) {
	            mid = Math.floor((start + end) / 2);
	            var midValue = this._animationEvents[mid].time;
	            if (midValue == time)
	                return mid;
	            else if (midValue > time)
	                end = mid - 1;
	            else
	                start = mid + 1;
	        }
	        return start;
	    }
	    addEvent(event) {
	        var index = this._binarySearchEventIndex(event.time);
	        this._animationEvents.splice(index, 0, event);
	    }
	    _disposeResource() {
	        this._nodes = null;
	        this._nodesMap = null;
	    }
	}
	AnimationClip.ANIMATIONCLIP = "ANIMATIONCLIP";
	AnimationClip._tempQuaternion0 = new Quaternion();

	class AnimatorPlayState {
	    get normalizedTime() {
	        return this._normalizedTime;
	    }
	    get duration() {
	        return this._duration;
	    }
	    constructor() {
	    }
	    _resetPlayState(startTime) {
	        this._finish = false;
	        this._startPlayTime = startTime;
	        this._elapsedTime = startTime;
	        this._playEventIndex = 0;
	        this._lastIsFront = true;
	    }
	    _cloneTo(dest) {
	        dest._finish = this._finish;
	        dest._startPlayTime = this._startPlayTime;
	        dest._elapsedTime = this._elapsedTime;
	        dest._playEventIndex = this._playEventIndex;
	        dest._lastIsFront = this._lastIsFront;
	    }
	}

	class AnimatorControllerLayer {
	    constructor(name) {
	        this._defaultState = null;
	        this._referenceCount = 0;
	        this._statesMap = {};
	        this.playOnWake = true;
	        this._playType = -1;
	        this._crossMark = 0;
	        this._crossDuration = -1;
	        this._crossNodesOwnersIndicesMap = {};
	        this._crossNodesOwnersCount = 0;
	        this._crossNodesOwners = [];
	        this._currentPlayState = null;
	        this._states = [];
	        this._playStateInfo = new AnimatorPlayState();
	        this._crossPlayStateInfo = new AnimatorPlayState();
	        this._srcCrossClipNodeIndices = [];
	        this._destCrossClipNodeIndices = [];
	        this.name = name;
	        this.defaultWeight = 1.0;
	        this.blendingMode = AnimatorControllerLayer.BLENDINGMODE_OVERRIDE;
	    }
	    get defaultState() {
	        return this._defaultState;
	    }
	    set defaultState(value) {
	        this._defaultState = value;
	        this._statesMap[value.name] = value;
	    }
	    _removeClip(clipStateInfos, statesMap, index, state) {
	        var clip = state._clip;
	        var clipStateInfo = clipStateInfos[index];
	        clipStateInfos.splice(index, 1);
	        delete statesMap[state.name];
	        if (this._animator) {
	            var frameNodes = clip._nodes;
	            var nodeOwners = clipStateInfo._nodeOwners;
	            clip._removeReference();
	            for (var i = 0, n = frameNodes.count; i < n; i++)
	                this._animator._removeKeyframeNodeOwner(nodeOwners, frameNodes.getNodeByIndex(i));
	        }
	    }
	    _getReferenceCount() {
	        return this._referenceCount;
	    }
	    _addReference(count = 1) {
	        for (var i = 0, n = this._states.length; i < n; i++)
	            this._states[i]._addReference(count);
	        this._referenceCount += count;
	    }
	    _removeReference(count = 1) {
	        for (var i = 0, n = this._states.length; i < n; i++)
	            this._states[i]._removeReference(count);
	        this._referenceCount -= count;
	    }
	    _clearReference() {
	        this._removeReference(-this._referenceCount);
	    }
	    getAnimatorState(name) {
	        var state = this._statesMap[name];
	        return state ? state : null;
	    }
	    addState(state) {
	        var stateName = state.name;
	        if (this._statesMap[stateName]) {
	            throw "AnimatorControllerLayer:this stat's name has exist.";
	        }
	        else {
	            this._statesMap[stateName] = state;
	            this._states.push(state);
	            if (this._animator) {
	                state._clip._addReference();
	                this._animator._getOwnersByClip(state);
	            }
	        }
	    }
	    removeState(state) {
	        var states = this._states;
	        var index = -1;
	        for (var i = 0, n = states.length; i < n; i++) {
	            if (states[i] === state) {
	                index = i;
	                break;
	            }
	        }
	        if (index !== -1)
	            this._removeClip(states, this._statesMap, index, state);
	    }
	    destroy() {
	        this._clearReference();
	        this._statesMap = null;
	        this._states = null;
	        this._playStateInfo = null;
	        this._crossPlayStateInfo = null;
	        this._defaultState = null;
	    }
	    cloneTo(destObject) {
	        var dest = destObject;
	        dest.name = this.name;
	        dest.blendingMode = this.blendingMode;
	        dest.defaultWeight = this.defaultWeight;
	        dest.playOnWake = this.playOnWake;
	    }
	    clone() {
	        var dest = new AnimatorControllerLayer(this.name);
	        this.cloneTo(dest);
	        return dest;
	    }
	}
	AnimatorControllerLayer.BLENDINGMODE_OVERRIDE = 0;
	AnimatorControllerLayer.BLENDINGMODE_ADDTIVE = 1;

	class AnimatorState {
	    constructor() {
	        this._referenceCount = 0;
	        this._clip = null;
	        this._nodeOwners = [];
	        this._currentFrameIndices = null;
	        this._scripts = null;
	        this.speed = 1.0;
	        this.clipStart = 0.0;
	        this.clipEnd = 1.0;
	    }
	    get clip() {
	        return this._clip;
	    }
	    set clip(value) {
	        if (this._clip !== value) {
	            if (this._clip)
	                (this._referenceCount > 0) && (this._clip._removeReference(this._referenceCount));
	            if (value) {
	                this._currentFrameIndices = new Int16Array(value._nodes.count);
	                this._resetFrameIndices();
	                (this._referenceCount > 0) && (this._clip._addReference(this._referenceCount));
	            }
	            this._clip = value;
	        }
	    }
	    _getReferenceCount() {
	        return this._referenceCount;
	    }
	    _addReference(count = 1) {
	        (this._clip) && (this._clip._addReference(count));
	        this._referenceCount += count;
	    }
	    _removeReference(count = 1) {
	        (this._clip) && (this._clip._removeReference(count));
	        this._referenceCount -= count;
	    }
	    _clearReference() {
	        this._removeReference(-this._referenceCount);
	    }
	    _resetFrameIndices() {
	        for (var i = 0, n = this._currentFrameIndices.length; i < n; i++)
	            this._currentFrameIndices[i] = -1;
	    }
	    addScript(type) {
	        var script = new type();
	        this._scripts = this._scripts || [];
	        this._scripts.push(script);
	        return script;
	    }
	    getScript(type) {
	        if (this._scripts) {
	            for (var i = 0, n = this._scripts.length; i < n; i++) {
	                var script = this._scripts[i];
	                if (script instanceof type)
	                    return script;
	            }
	        }
	        return null;
	    }
	    getScripts(type) {
	        var coms;
	        if (this._scripts) {
	            for (var i = 0, n = this._scripts.length; i < n; i++) {
	                var script = this._scripts[i];
	                if (script instanceof type) {
	                    coms = coms || [];
	                    coms.push(script);
	                }
	            }
	        }
	        return coms;
	    }
	    cloneTo(destObject) {
	        var dest = destObject;
	        dest.name = this.name;
	        dest.speed = this.speed;
	        dest.clipStart = this.clipStart;
	        dest.clipEnd = this.clipEnd;
	        dest.clip = this._clip;
	    }
	    clone() {
	        var dest = new AnimatorState();
	        this.cloneTo(dest);
	        return dest;
	    }
	}

	class KeyframeNodeOwner {
	    constructor() {
	        this.indexInList = -1;
	        this.referenceCount = 0;
	        this.updateMark = -1;
	        this.type = -1;
	        this.fullPath = null;
	        this.propertyOwner = null;
	        this.property = null;
	        this.defaultValue = null;
	        this.crossFixedValue = null;
	    }
	    saveCrossFixedValue() {
	        var pro = this.propertyOwner;
	        if (pro) {
	            switch (this.type) {
	                case 0:
	                    var proPat = this.property;
	                    var m = proPat.length - 1;
	                    for (var j = 0; j < m; j++) {
	                        pro = pro[proPat[j]];
	                        if (!pro)
	                            break;
	                    }
	                    this.crossFixedValue = pro[proPat[m]];
	                    break;
	                case 1:
	                    var locPos = pro.localPosition;
	                    this.crossFixedValue || (this.crossFixedValue = new Vector3());
	                    this.crossFixedValue.x = locPos.x;
	                    this.crossFixedValue.y = locPos.y;
	                    this.crossFixedValue.z = locPos.z;
	                    break;
	                case 2:
	                    var locRot = pro.localRotation;
	                    this.crossFixedValue || (this.crossFixedValue = new Quaternion());
	                    this.crossFixedValue.x = locRot.x;
	                    this.crossFixedValue.y = locRot.y;
	                    this.crossFixedValue.z = locRot.z;
	                    this.crossFixedValue.w = locRot.w;
	                    break;
	                case 3:
	                    var locSca = pro.localScale;
	                    this.crossFixedValue || (this.crossFixedValue = new Vector3());
	                    this.crossFixedValue.x = locSca.x;
	                    this.crossFixedValue.y = locSca.y;
	                    this.crossFixedValue.z = locSca.z;
	                    break;
	                case 4:
	                    var locEul = pro.localRotationEuler;
	                    this.crossFixedValue || (this.crossFixedValue = new Vector3());
	                    this.crossFixedValue.x = locEul.x;
	                    this.crossFixedValue.y = locEul.y;
	                    this.crossFixedValue.z = locEul.z;
	                    break;
	                default:
	                    throw "Animator:unknown type.";
	            }
	        }
	    }
	}

	class Animator extends Laya.Component {
	    constructor() {
	        super();
	        this._keyframeNodeOwners = [];
	        this._linkAvatarSpritesData = {};
	        this._linkAvatarSprites = [];
	        this._renderableSprites = [];
	        this.cullingMode = Animator.CULLINGMODE_CULLCOMPLETELY;
	        this._controllerLayers = [];
	        this._linkSprites = {};
	        this._speed = 1.0;
	        this._keyframeNodeOwnerMap = {};
	        this._updateMark = 0;
	    }
	    static _update(scene) {
	        var pool = scene._animatorPool;
	        var elements = pool.elements;
	        for (var i = 0, n = pool.length; i < n; i++) {
	            var animator = elements[i];
	            (animator && animator.enabled) && (animator._update());
	        }
	    }
	    get speed() {
	        return this._speed;
	    }
	    set speed(value) {
	        this._speed = value;
	    }
	    _linkToSprites(linkSprites) {
	        for (var k in linkSprites) {
	            var nodeOwner = this.owner;
	            var path = linkSprites[k];
	            for (var j = 0, m = path.length; j < m; j++) {
	                var p = path[j];
	                if (p === "") {
	                    break;
	                }
	                else {
	                    nodeOwner = nodeOwner.getChildByName(p);
	                    if (!nodeOwner)
	                        break;
	                }
	            }
	            (nodeOwner) && (this.linkSprite3DToAvatarNode(k, nodeOwner));
	        }
	    }
	    _addKeyframeNodeOwner(clipOwners, node, propertyOwner) {
	        var nodeIndex = node._indexInList;
	        var fullPath = node.fullPath;
	        var keyframeNodeOwner = this._keyframeNodeOwnerMap[fullPath];
	        if (keyframeNodeOwner) {
	            keyframeNodeOwner.referenceCount++;
	            clipOwners[nodeIndex] = keyframeNodeOwner;
	        }
	        else {
	            var property = propertyOwner;
	            for (var i = 0, n = node.propertyCount; i < n; i++) {
	                property = property[node.getPropertyByIndex(i)];
	                if (!property)
	                    break;
	            }
	            keyframeNodeOwner = this._keyframeNodeOwnerMap[fullPath] = new KeyframeNodeOwner();
	            keyframeNodeOwner.fullPath = fullPath;
	            keyframeNodeOwner.indexInList = this._keyframeNodeOwners.length;
	            keyframeNodeOwner.referenceCount = 1;
	            keyframeNodeOwner.propertyOwner = propertyOwner;
	            var propertyCount = node.propertyCount;
	            var propertys = [];
	            for (i = 0; i < propertyCount; i++)
	                propertys[i] = node.getPropertyByIndex(i);
	            keyframeNodeOwner.property = propertys;
	            keyframeNodeOwner.type = node.type;
	            if (property) {
	                if (node.type === 0) {
	                    keyframeNodeOwner.defaultValue = property;
	                }
	                else {
	                    var defaultValue = new property.constructor();
	                    property.cloneTo(defaultValue);
	                    keyframeNodeOwner.defaultValue = defaultValue;
	                }
	            }
	            this._keyframeNodeOwners.push(keyframeNodeOwner);
	            clipOwners[nodeIndex] = keyframeNodeOwner;
	        }
	    }
	    _removeKeyframeNodeOwner(nodeOwners, node) {
	        var fullPath = node.fullPath;
	        var keyframeNodeOwner = this._keyframeNodeOwnerMap[fullPath];
	        if (keyframeNodeOwner) {
	            keyframeNodeOwner.referenceCount--;
	            if (keyframeNodeOwner.referenceCount === 0) {
	                delete this._keyframeNodeOwnerMap[fullPath];
	                this._keyframeNodeOwners.splice(this._keyframeNodeOwners.indexOf(keyframeNodeOwner), 1);
	            }
	            nodeOwners[node._indexInList] = null;
	        }
	    }
	    _getOwnersByClip(clipStateInfo) {
	        var frameNodes = clipStateInfo._clip._nodes;
	        var frameNodesCount = frameNodes.count;
	        var nodeOwners = clipStateInfo._nodeOwners;
	        nodeOwners.length = frameNodesCount;
	        for (var i = 0; i < frameNodesCount; i++) {
	            var node = frameNodes.getNodeByIndex(i);
	            var property = this._avatar ? this._avatarNodeMap[this._avatar._rootNode.name] : this.owner;
	            for (var j = 0, m = node.ownerPathCount; j < m; j++) {
	                var ownPat = node.getOwnerPathByIndex(j);
	                if (ownPat === "") {
	                    break;
	                }
	                else {
	                    property = property.getChildByName(ownPat);
	                    if (!property)
	                        break;
	                }
	            }
	            if (property) {
	                var propertyOwner = node.propertyOwner;
	                (propertyOwner) && (property = property[propertyOwner]);
	                property && this._addKeyframeNodeOwner(nodeOwners, node, property);
	            }
	        }
	    }
	    _updatePlayer(animatorState, playState, elapsedTime, islooping) {
	        var clipDuration = animatorState._clip._duration * (animatorState.clipEnd - animatorState.clipStart);
	        var lastElapsedTime = playState._elapsedTime;
	        var elapsedPlaybackTime = lastElapsedTime + elapsedTime;
	        playState._lastElapsedTime = lastElapsedTime;
	        playState._elapsedTime = elapsedPlaybackTime;
	        var normalizedTime = elapsedPlaybackTime / clipDuration;
	        playState._normalizedTime = normalizedTime;
	        var playTime = normalizedTime % 1.0;
	        playState._normalizedPlayTime = playTime < 0 ? playTime + 1.0 : playTime;
	        playState._duration = clipDuration;
	        var scripts = animatorState._scripts;
	        if ((!islooping && elapsedPlaybackTime >= clipDuration)) {
	            playState._finish = true;
	            playState._elapsedTime = clipDuration;
	            playState._normalizedPlayTime = 1.0;
	            if (scripts) {
	                for (var i = 0, n = scripts.length; i < n; i++)
	                    scripts[i].onStateExit();
	            }
	            return;
	        }
	        if (scripts) {
	            for (i = 0, n = scripts.length; i < n; i++)
	                scripts[i].onStateUpdate();
	        }
	    }
	    _eventScript(scripts, events, eventIndex, endTime, front) {
	        if (front) {
	            for (var n = events.length; eventIndex < n; eventIndex++) {
	                var event = events[eventIndex];
	                if (event.time <= endTime) {
	                    for (var j = 0, m = scripts.length; j < m; j++) {
	                        var script = scripts[j];
	                        var fun = script[event.eventName];
	                        (fun) && (fun.apply(script, event.params));
	                    }
	                }
	                else {
	                    break;
	                }
	            }
	        }
	        else {
	            for (; eventIndex >= 0; eventIndex--) {
	                event = events[eventIndex];
	                if (event.time >= endTime) {
	                    for (j = 0, m = scripts.length; j < m; j++) {
	                        script = scripts[j];
	                        fun = script[event.eventName];
	                        (fun) && (fun.apply(script, event.params));
	                    }
	                }
	                else {
	                    break;
	                }
	            }
	        }
	        return eventIndex;
	    }
	    _updateEventScript(stateInfo, playStateInfo) {
	        var scripts = this.owner._scripts;
	        if (scripts) {
	            var clip = stateInfo._clip;
	            var events = clip._animationEvents;
	            var clipDuration = clip._duration;
	            var elapsedTime = playStateInfo._elapsedTime;
	            var time = elapsedTime % clipDuration;
	            var loopCount = Math.abs(Math.floor(elapsedTime / clipDuration) - Math.floor(playStateInfo._lastElapsedTime / clipDuration));
	            var frontPlay = playStateInfo._elapsedTime >= playStateInfo._lastElapsedTime;
	            if (playStateInfo._lastIsFront !== frontPlay) {
	                if (frontPlay)
	                    playStateInfo._playEventIndex++;
	                else
	                    playStateInfo._playEventIndex--;
	                playStateInfo._lastIsFront = frontPlay;
	            }
	            if (loopCount == 0) {
	                playStateInfo._playEventIndex = this._eventScript(scripts, events, playStateInfo._playEventIndex, time, frontPlay);
	            }
	            else {
	                if (frontPlay) {
	                    this._eventScript(scripts, events, playStateInfo._playEventIndex, clipDuration, true);
	                    for (var i = 0, n = loopCount - 1; i < n; i++)
	                        this._eventScript(scripts, events, 0, clipDuration, true);
	                    playStateInfo._playEventIndex = this._eventScript(scripts, events, 0, time, true);
	                }
	                else {
	                    this._eventScript(scripts, events, playStateInfo._playEventIndex, 0, false);
	                    var eventIndex = events.length - 1;
	                    for (i = 0, n = loopCount - 1; i < n; i++)
	                        this._eventScript(scripts, events, eventIndex, 0, false);
	                    playStateInfo._playEventIndex = this._eventScript(scripts, events, eventIndex, time, false);
	                }
	            }
	        }
	    }
	    _updateClipDatas(animatorState, addtive, playStateInfo, scale) {
	        var clip = animatorState._clip;
	        var clipDuration = clip._duration;
	        var curPlayTime = animatorState.clipStart * clipDuration + playStateInfo._normalizedPlayTime * playStateInfo._duration;
	        var currentFrameIndices = animatorState._currentFrameIndices;
	        var frontPlay = playStateInfo._elapsedTime > playStateInfo._lastElapsedTime;
	        clip._evaluateClipDatasRealTime(clip._nodes, curPlayTime, currentFrameIndices, addtive, frontPlay);
	    }
	    _applyFloat(pro, proName, nodeOwner, additive, weight, isFirstLayer, data) {
	        if (nodeOwner.updateMark === this._updateMark) {
	            if (additive) {
	                pro[proName] += weight * (data);
	            }
	            else {
	                var oriValue = pro[proName];
	                pro[proName] = oriValue + weight * (data - oriValue);
	            }
	        }
	        else {
	            if (isFirstLayer) {
	                if (additive)
	                    pro[proName] = nodeOwner.defaultValue + data;
	                else
	                    pro[proName] = data;
	            }
	            else {
	                if (additive) {
	                    pro[proName] = nodeOwner.defaultValue + weight * (data);
	                }
	                else {
	                    var defValue = nodeOwner.defaultValue;
	                    pro[proName] = defValue + weight * (data - defValue);
	                }
	            }
	        }
	    }
	    _applyPositionAndRotationEuler(nodeOwner, additive, weight, isFirstLayer, data, out) {
	        if (nodeOwner.updateMark === this._updateMark) {
	            if (additive) {
	                out.x += weight * data.x;
	                out.y += weight * data.y;
	                out.z += weight * data.z;
	            }
	            else {
	                var oriX = out.x;
	                var oriY = out.y;
	                var oriZ = out.z;
	                out.x = oriX + weight * (data.x - oriX);
	                out.y = oriY + weight * (data.y - oriY);
	                out.z = oriZ + weight * (data.z - oriZ);
	            }
	        }
	        else {
	            if (isFirstLayer) {
	                if (additive) {
	                    var defValue = nodeOwner.defaultValue;
	                    out.x = defValue.x + data.x;
	                    out.y = defValue.y + data.y;
	                    out.z = defValue.z + data.z;
	                }
	                else {
	                    out.x = data.x;
	                    out.y = data.y;
	                    out.z = data.z;
	                }
	            }
	            else {
	                defValue = nodeOwner.defaultValue;
	                if (additive) {
	                    out.x = defValue.x + weight * data.x;
	                    out.y = defValue.y + weight * data.y;
	                    out.z = defValue.z + weight * data.z;
	                }
	                else {
	                    var defX = defValue.x;
	                    var defY = defValue.y;
	                    var defZ = defValue.z;
	                    out.x = defX + weight * (data.x - defX);
	                    out.y = defY + weight * (data.y - defY);
	                    out.z = defZ + weight * (data.z - defZ);
	                }
	            }
	        }
	    }
	    _applyRotation(nodeOwner, additive, weight, isFirstLayer, clipRot, localRotation) {
	        if (nodeOwner.updateMark === this._updateMark) {
	            if (additive) {
	                var tempQuat = Animator._tempQuaternion1;
	                Utils3D.quaternionWeight(clipRot, weight, tempQuat);
	                tempQuat.normalize(tempQuat);
	                Quaternion.multiply(localRotation, tempQuat, localRotation);
	            }
	            else {
	                Quaternion.lerp(localRotation, clipRot, weight, localRotation);
	            }
	        }
	        else {
	            if (isFirstLayer) {
	                if (additive) {
	                    var defaultRot = nodeOwner.defaultValue;
	                    Quaternion.multiply(defaultRot, clipRot, localRotation);
	                }
	                else {
	                    localRotation.x = clipRot.x;
	                    localRotation.y = clipRot.y;
	                    localRotation.z = clipRot.z;
	                    localRotation.w = clipRot.w;
	                }
	            }
	            else {
	                defaultRot = nodeOwner.defaultValue;
	                if (additive) {
	                    tempQuat = Animator._tempQuaternion1;
	                    Utils3D.quaternionWeight(clipRot, weight, tempQuat);
	                    tempQuat.normalize(tempQuat);
	                    Quaternion.multiply(defaultRot, tempQuat, localRotation);
	                }
	                else {
	                    Quaternion.lerp(defaultRot, clipRot, weight, localRotation);
	                }
	            }
	        }
	    }
	    _applyScale(nodeOwner, additive, weight, isFirstLayer, clipSca, localScale) {
	        if (nodeOwner.updateMark === this._updateMark) {
	            if (additive) {
	                var scale = Animator._tempVector31;
	                Utils3D.scaleWeight(clipSca, weight, scale);
	                localScale.x = localScale.x * scale.x;
	                localScale.y = localScale.y * scale.y;
	                localScale.z = localScale.z * scale.z;
	            }
	            else {
	                Utils3D.scaleBlend(localScale, clipSca, weight, localScale);
	            }
	        }
	        else {
	            if (isFirstLayer) {
	                if (additive) {
	                    var defaultSca = nodeOwner.defaultValue;
	                    localScale.x = defaultSca.x * clipSca.x;
	                    localScale.y = defaultSca.y * clipSca.y;
	                    localScale.z = defaultSca.z * clipSca.z;
	                }
	                else {
	                    localScale.x = clipSca.x;
	                    localScale.y = clipSca.y;
	                    localScale.z = clipSca.z;
	                }
	            }
	            else {
	                defaultSca = nodeOwner.defaultValue;
	                if (additive) {
	                    scale = Animator._tempVector31;
	                    Utils3D.scaleWeight(clipSca, weight, scale);
	                    localScale.x = defaultSca.x * scale.x;
	                    localScale.y = defaultSca.y * scale.y;
	                    localScale.z = defaultSca.z * scale.z;
	                }
	                else {
	                    Utils3D.scaleBlend(defaultSca, clipSca, weight, localScale);
	                }
	            }
	        }
	    }
	    _applyCrossData(nodeOwner, additive, weight, isFirstLayer, srcValue, desValue, crossWeight) {
	        var pro = nodeOwner.propertyOwner;
	        if (pro) {
	            switch (nodeOwner.type) {
	                case 0:
	                    var proPat = nodeOwner.property;
	                    var m = proPat.length - 1;
	                    for (var j = 0; j < m; j++) {
	                        pro = pro[proPat[j]];
	                        if (!pro)
	                            break;
	                    }
	                    var crossValue = srcValue + crossWeight * (desValue - srcValue);
	                    this._applyFloat(pro, proPat[m], nodeOwner, additive, weight, isFirstLayer, crossValue);
	                    break;
	                case 1:
	                    var localPos = pro.localPosition;
	                    var position = Animator._tempVector30;
	                    var srcX = srcValue.x, srcY = srcValue.y, srcZ = srcValue.z;
	                    position.x = srcX + crossWeight * (desValue.x - srcX);
	                    position.y = srcY + crossWeight * (desValue.y - srcY);
	                    position.z = srcZ + crossWeight * (desValue.z - srcZ);
	                    this._applyPositionAndRotationEuler(nodeOwner, additive, weight, isFirstLayer, position, localPos);
	                    pro.localPosition = localPos;
	                    break;
	                case 2:
	                    var localRot = pro.localRotation;
	                    var rotation = Animator._tempQuaternion0;
	                    Quaternion.lerp(srcValue, desValue, crossWeight, rotation);
	                    this._applyRotation(nodeOwner, additive, weight, isFirstLayer, rotation, localRot);
	                    pro.localRotation = localRot;
	                    break;
	                case 3:
	                    var localSca = pro.localScale;
	                    var scale = Animator._tempVector30;
	                    Utils3D.scaleBlend(srcValue, desValue, crossWeight, scale);
	                    this._applyScale(nodeOwner, additive, weight, isFirstLayer, scale, localSca);
	                    pro.localScale = localSca;
	                    break;
	                case 4:
	                    var localEuler = pro.localRotationEuler;
	                    var rotationEuler = Animator._tempVector30;
	                    srcX = srcValue.x, srcY = srcValue.y, srcZ = srcValue.z;
	                    rotationEuler.x = srcX + crossWeight * (desValue.x - srcX);
	                    rotationEuler.y = srcY + crossWeight * (desValue.y - srcY);
	                    rotationEuler.z = srcZ + crossWeight * (desValue.z - srcZ);
	                    this._applyPositionAndRotationEuler(nodeOwner, additive, weight, isFirstLayer, rotationEuler, localEuler);
	                    pro.localRotationEuler = localEuler;
	                    break;
	            }
	            nodeOwner.updateMark = this._updateMark;
	        }
	    }
	    _setClipDatasToNode(stateInfo, additive, weight, isFirstLayer) {
	        var nodes = stateInfo._clip._nodes;
	        var nodeOwners = stateInfo._nodeOwners;
	        for (var i = 0, n = nodes.count; i < n; i++) {
	            var nodeOwner = nodeOwners[i];
	            if (nodeOwner) {
	                var pro = nodeOwner.propertyOwner;
	                if (pro) {
	                    switch (nodeOwner.type) {
	                        case 0:
	                            var proPat = nodeOwner.property;
	                            var m = proPat.length - 1;
	                            for (var j = 0; j < m; j++) {
	                                pro = pro[proPat[j]];
	                                if (!pro)
	                                    break;
	                            }
	                            this._applyFloat(pro, proPat[m], nodeOwner, additive, weight, isFirstLayer, nodes.getNodeByIndex(i).data);
	                            break;
	                        case 1:
	                            var localPos = pro.localPosition;
	                            this._applyPositionAndRotationEuler(nodeOwner, additive, weight, isFirstLayer, nodes.getNodeByIndex(i).data, localPos);
	                            pro.localPosition = localPos;
	                            break;
	                        case 2:
	                            var localRot = pro.localRotation;
	                            this._applyRotation(nodeOwner, additive, weight, isFirstLayer, nodes.getNodeByIndex(i).data, localRot);
	                            pro.localRotation = localRot;
	                            break;
	                        case 3:
	                            var localSca = pro.localScale;
	                            this._applyScale(nodeOwner, additive, weight, isFirstLayer, nodes.getNodeByIndex(i).data, localSca);
	                            pro.localScale = localSca;
	                            break;
	                        case 4:
	                            var localEuler = pro.localRotationEuler;
	                            this._applyPositionAndRotationEuler(nodeOwner, additive, weight, isFirstLayer, nodes.getNodeByIndex(i).data, localEuler);
	                            pro.localRotationEuler = localEuler;
	                            break;
	                    }
	                    nodeOwner.updateMark = this._updateMark;
	                }
	            }
	        }
	    }
	    _setCrossClipDatasToNode(controllerLayer, srcState, destState, crossWeight, isFirstLayer) {
	        var nodeOwners = controllerLayer._crossNodesOwners;
	        var ownerCount = controllerLayer._crossNodesOwnersCount;
	        var additive = controllerLayer.blendingMode !== AnimatorControllerLayer.BLENDINGMODE_OVERRIDE;
	        var weight = controllerLayer.defaultWeight;
	        var destDataIndices = controllerLayer._destCrossClipNodeIndices;
	        var destNodes = destState._clip._nodes;
	        var destNodeOwners = destState._nodeOwners;
	        var srcDataIndices = controllerLayer._srcCrossClipNodeIndices;
	        var srcNodeOwners = srcState._nodeOwners;
	        var srcNodes = srcState._clip._nodes;
	        for (var i = 0; i < ownerCount; i++) {
	            var nodeOwner = nodeOwners[i];
	            if (nodeOwner) {
	                var srcIndex = srcDataIndices[i];
	                var destIndex = destDataIndices[i];
	                var srcValue = srcIndex !== -1 ? srcNodes.getNodeByIndex(srcIndex).data : destNodeOwners[destIndex].defaultValue;
	                var desValue = destIndex !== -1 ? destNodes.getNodeByIndex(destIndex).data : srcNodeOwners[srcIndex].defaultValue;
	                this._applyCrossData(nodeOwner, additive, weight, isFirstLayer, srcValue, desValue, crossWeight);
	            }
	        }
	    }
	    _setFixedCrossClipDatasToNode(controllerLayer, destState, crossWeight, isFirstLayer) {
	        var nodeOwners = controllerLayer._crossNodesOwners;
	        var ownerCount = controllerLayer._crossNodesOwnersCount;
	        var additive = controllerLayer.blendingMode !== AnimatorControllerLayer.BLENDINGMODE_OVERRIDE;
	        var weight = controllerLayer.defaultWeight;
	        var destDataIndices = controllerLayer._destCrossClipNodeIndices;
	        var destNodes = destState._clip._nodes;
	        for (var i = 0; i < ownerCount; i++) {
	            var nodeOwner = nodeOwners[i];
	            if (nodeOwner) {
	                var destIndex = destDataIndices[i];
	                var srcValue = nodeOwner.crossFixedValue;
	                var desValue = destIndex !== -1 ? destNodes.getNodeByIndex(destIndex).data : nodeOwner.defaultValue;
	                this._applyCrossData(nodeOwner, additive, weight, isFirstLayer, srcValue, desValue, crossWeight);
	            }
	        }
	    }
	    _revertDefaultKeyframeNodes(clipStateInfo) {
	        var nodeOwners = clipStateInfo._nodeOwners;
	        for (var i = 0, n = nodeOwners.length; i < n; i++) {
	            var nodeOwner = nodeOwners[i];
	            if (nodeOwner) {
	                var pro = nodeOwner.propertyOwner;
	                if (pro) {
	                    switch (nodeOwner.type) {
	                        case 0:
	                            var proPat = nodeOwner.property;
	                            var m = proPat.length - 1;
	                            for (var j = 0; j < m; j++) {
	                                pro = pro[proPat[j]];
	                                if (!pro)
	                                    break;
	                            }
	                            pro[proPat[m]] = nodeOwner.defaultValue;
	                            break;
	                        case 1:
	                            var locPos = pro.localPosition;
	                            var def = nodeOwner.defaultValue;
	                            locPos.x = def.x;
	                            locPos.y = def.y;
	                            locPos.z = def.z;
	                            pro.localPosition = locPos;
	                            break;
	                        case 2:
	                            var locRot = pro.localRotation;
	                            var defQua = nodeOwner.defaultValue;
	                            locRot.x = defQua.x;
	                            locRot.y = defQua.y;
	                            locRot.z = defQua.z;
	                            locRot.w = defQua.w;
	                            pro.localRotation = locRot;
	                            break;
	                        case 3:
	                            var locSca = pro.localScale;
	                            def = nodeOwner.defaultValue;
	                            locSca.x = def.x;
	                            locSca.y = def.y;
	                            locSca.z = def.z;
	                            pro.localScale = locSca;
	                            break;
	                        case 4:
	                            var locEul = pro.localRotationEuler;
	                            def = nodeOwner.defaultValue;
	                            locEul.x = def.x;
	                            locEul.y = def.y;
	                            locEul.z = def.z;
	                            pro.localRotationEuler = locEul;
	                            break;
	                        default:
	                            throw "Animator:unknown type.";
	                    }
	                }
	            }
	        }
	    }
	    _onAdded() {
	        var parent = this.owner._parent;
	        this.owner._setHierarchyAnimator(this, parent ? parent._hierarchyAnimator : null);
	        this.owner._changeAnimatorToLinkSprite3DNoAvatar(this, true, []);
	    }
	    _onDestroy() {
	        for (var i = 0, n = this._controllerLayers.length; i < n; i++)
	            this._controllerLayers[i]._removeReference();
	        var parent = this.owner._parent;
	        this.owner._clearHierarchyAnimator(this, parent ? parent._hierarchyAnimator : null);
	    }
	    _onEnable() {
	        this.owner._scene._animatorPool.add(this);
	        for (var i = 0, n = this._controllerLayers.length; i < n; i++) {
	            if (this._controllerLayers[i].playOnWake) {
	                var defaultClip = this.getDefaultState(i);
	                (defaultClip) && (this.play(null, i, 0));
	            }
	        }
	    }
	    _onDisable() {
	        this.owner._scene._animatorPool.remove(this);
	    }
	    _handleSpriteOwnersBySprite(isLink, path, sprite) {
	        for (var i = 0, n = this._controllerLayers.length; i < n; i++) {
	            var clipStateInfos = this._controllerLayers[i]._states;
	            for (var j = 0, m = clipStateInfos.length; j < m; j++) {
	                var clipStateInfo = clipStateInfos[j];
	                var clip = clipStateInfo._clip;
	                var nodePath = path.join("/");
	                var ownersNodes = clip._nodesMap[nodePath];
	                if (ownersNodes) {
	                    var nodeOwners = clipStateInfo._nodeOwners;
	                    for (var k = 0, p = ownersNodes.length; k < p; k++) {
	                        if (isLink)
	                            this._addKeyframeNodeOwner(nodeOwners, ownersNodes[k], sprite);
	                        else
	                            this._removeKeyframeNodeOwner(nodeOwners, ownersNodes[k]);
	                    }
	                }
	            }
	        }
	    }
	    _parse(data) {
	        var avatarData = data.avatar;
	        if (avatarData) {
	            this.avatar = Laya.Loader.getRes(avatarData.path);
	            var linkSprites = avatarData.linkSprites;
	            this._linkSprites = linkSprites;
	            this._linkToSprites(linkSprites);
	        }
	        var clipPaths = data.clipPaths;
	        var play = data.playOnWake;
	        var layersData = data.layers;
	        for (var i = 0; i < layersData.length; i++) {
	            var layerData = layersData[i];
	            var animatorLayer = new AnimatorControllerLayer(layerData.name);
	            if (i === 0)
	                animatorLayer.defaultWeight = 1.0;
	            else
	                animatorLayer.defaultWeight = layerData.weight;
	            var blendingModeData = layerData.blendingMode;
	            (blendingModeData) && (animatorLayer.blendingMode = blendingModeData);
	            this.addControllerLayer(animatorLayer);
	            var states = layerData.states;
	            for (var j = 0, m = states.length; j < m; j++) {
	                var state = states[j];
	                var clipPath = state.clipPath;
	                if (clipPath) {
	                    var name = state.name;
	                    var motion;
	                    motion = Laya.Loader.getRes(clipPath);
	                    if (motion) {
	                        var animatorState = new AnimatorState();
	                        animatorState.name = name;
	                        animatorState.clip = motion;
	                        animatorLayer.addState(animatorState);
	                        (j === 0) && (this.getControllerLayer(i).defaultState = animatorState);
	                    }
	                }
	            }
	            (play !== undefined) && (animatorLayer.playOnWake = play);
	        }
	        var cullingModeData = data.cullingMode;
	        (cullingModeData !== undefined) && (this.cullingMode = cullingModeData);
	    }
	    _update() {
	        var timer = this.owner._scene.timer;
	        var delta = timer._delta / 1000.0;
	        if (this._speed === 0 || delta === 0)
	            return;
	        var needRender;
	        if (this.cullingMode === Animator.CULLINGMODE_CULLCOMPLETELY) {
	            needRender = false;
	            for (var i = 0, n = this._renderableSprites.length; i < n; i++) {
	                if (this._renderableSprites[i]._render._visible) {
	                    needRender = true;
	                    break;
	                }
	            }
	        }
	        else {
	            needRender = true;
	        }
	        this._updateMark++;
	        var timerScale = timer.scale;
	        for (i = 0, n = this._controllerLayers.length; i < n; i++) {
	            var controllerLayer = this._controllerLayers[i];
	            var playStateInfo = controllerLayer._playStateInfo;
	            var crossPlayStateInfo = controllerLayer._crossPlayStateInfo;
	            addtive = controllerLayer.blendingMode !== AnimatorControllerLayer.BLENDINGMODE_OVERRIDE;
	            switch (controllerLayer._playType) {
	                case 0:
	                    var animatorState = controllerLayer._currentPlayState;
	                    var clip = animatorState._clip;
	                    var speed = this._speed * animatorState.speed;
	                    var finish = playStateInfo._finish;
	                    finish || this._updatePlayer(animatorState, playStateInfo, delta * speed, clip.islooping);
	                    if (needRender) {
	                        var addtive = controllerLayer.blendingMode !== AnimatorControllerLayer.BLENDINGMODE_OVERRIDE;
	                        this._updateClipDatas(animatorState, addtive, playStateInfo, timerScale * speed);
	                        this._setClipDatasToNode(animatorState, addtive, controllerLayer.defaultWeight, i === 0);
	                        finish || this._updateEventScript(animatorState, playStateInfo);
	                    }
	                    break;
	                case 1:
	                    animatorState = controllerLayer._currentPlayState;
	                    clip = animatorState._clip;
	                    var crossClipState = controllerLayer._crossPlayState;
	                    var crossClip = crossClipState._clip;
	                    var crossDuratuion = controllerLayer._crossDuration;
	                    var startPlayTime = crossPlayStateInfo._startPlayTime;
	                    var crossClipDuration = crossClip._duration - startPlayTime;
	                    var crossScale = crossDuratuion > crossClipDuration ? crossClipDuration / crossDuratuion : 1.0;
	                    var crossSpeed = this._speed * crossClipState.speed;
	                    this._updatePlayer(crossClipState, crossPlayStateInfo, delta * crossScale * crossSpeed, crossClip.islooping);
	                    var crossWeight = ((crossPlayStateInfo._elapsedTime - startPlayTime) / crossScale) / crossDuratuion;
	                    if (crossWeight >= 1.0) {
	                        if (needRender) {
	                            this._updateClipDatas(crossClipState, addtive, crossPlayStateInfo, timerScale * crossSpeed);
	                            this._setClipDatasToNode(crossClipState, addtive, controllerLayer.defaultWeight, i === 0);
	                            controllerLayer._playType = 0;
	                            controllerLayer._currentPlayState = crossClipState;
	                            crossPlayStateInfo._cloneTo(playStateInfo);
	                        }
	                    }
	                    else {
	                        if (!playStateInfo._finish) {
	                            speed = this._speed * animatorState.speed;
	                            this._updatePlayer(animatorState, playStateInfo, delta * speed, clip.islooping);
	                        }
	                        if (needRender) {
	                            this._updateClipDatas(animatorState, addtive, playStateInfo, timerScale * speed);
	                            this._updateClipDatas(crossClipState, addtive, crossPlayStateInfo, timerScale * crossScale * crossSpeed);
	                            this._setCrossClipDatasToNode(controllerLayer, animatorState, crossClipState, crossWeight, i === 0);
	                        }
	                    }
	                    if (needRender) {
	                        this._updateEventScript(animatorState, playStateInfo);
	                        this._updateEventScript(crossClipState, crossPlayStateInfo);
	                    }
	                    break;
	                case 2:
	                    crossClipState = controllerLayer._crossPlayState;
	                    crossClip = crossClipState._clip;
	                    crossDuratuion = controllerLayer._crossDuration;
	                    startPlayTime = crossPlayStateInfo._startPlayTime;
	                    crossClipDuration = crossClip._duration - startPlayTime;
	                    crossScale = crossDuratuion > crossClipDuration ? crossClipDuration / crossDuratuion : 1.0;
	                    crossSpeed = this._speed * crossClipState.speed;
	                    this._updatePlayer(crossClipState, crossPlayStateInfo, delta * crossScale * crossSpeed, crossClip.islooping);
	                    if (needRender) {
	                        crossWeight = ((crossPlayStateInfo._elapsedTime - startPlayTime) / crossScale) / crossDuratuion;
	                        if (crossWeight >= 1.0) {
	                            this._updateClipDatas(crossClipState, addtive, crossPlayStateInfo, timerScale * crossSpeed);
	                            this._setClipDatasToNode(crossClipState, addtive, 1.0, i === 0);
	                            controllerLayer._playType = 0;
	                            controllerLayer._currentPlayState = crossClipState;
	                            crossPlayStateInfo._cloneTo(playStateInfo);
	                        }
	                        else {
	                            this._updateClipDatas(crossClipState, addtive, crossPlayStateInfo, timerScale * crossScale * crossSpeed);
	                            this._setFixedCrossClipDatasToNode(controllerLayer, crossClipState, crossWeight, i === 0);
	                        }
	                        this._updateEventScript(crossClipState, crossPlayStateInfo);
	                    }
	                    break;
	            }
	        }
	        if (needRender) {
	            if (this._avatar) {
	                Laya.Render.supportWebGLPlusAnimation && this._updateAnimationNodeWorldMatix(this._animationNodeLocalPositions, this._animationNodeLocalRotations, this._animationNodeLocalScales, this._animationNodeWorldMatrixs, this._animationNodeParentIndices);
	                this._updateAvatarNodesToSprite();
	            }
	        }
	    }
	    _cloneTo(dest) {
	        var animator = dest;
	        animator.avatar = this.avatar;
	        animator.cullingMode = this.cullingMode;
	        for (var i = 0, n = this._controllerLayers.length; i < n; i++) {
	            var controllLayer = this._controllerLayers[i];
	            animator.addControllerLayer(controllLayer.clone());
	            var animatorStates = controllLayer._states;
	            for (var j = 0, m = animatorStates.length; j < m; j++) {
	                var state = animatorStates[j].clone();
	                var cloneLayer = animator.getControllerLayer(i);
	                cloneLayer.addState(state);
	                (j == 0) && (cloneLayer.defaultState = state);
	            }
	        }
	        animator._linkSprites = this._linkSprites;
	        animator._linkToSprites(this._linkSprites);
	    }
	    getDefaultState(layerIndex = 0) {
	        var controllerLayer = this._controllerLayers[layerIndex];
	        return controllerLayer.defaultState;
	    }
	    addState(state, layerIndex = 0) {
	        var controllerLayer = this._controllerLayers[layerIndex];
	        controllerLayer.addState(state);
	        console.warn("Animator:this function is discard,please use animatorControllerLayer.addState() instead.");
	    }
	    removeState(state, layerIndex = 0) {
	        var controllerLayer = this._controllerLayers[layerIndex];
	        controllerLayer.removeState(state);
	        console.warn("Animator:this function is discard,please use animatorControllerLayer.removeState() instead.");
	    }
	    addControllerLayer(controllderLayer) {
	        this._controllerLayers.push(controllderLayer);
	        controllderLayer._animator = this;
	        controllderLayer._addReference();
	        var states = controllderLayer._states;
	        for (var i = 0, n = states.length; i < n; i++)
	            this._getOwnersByClip(states[i]);
	    }
	    getControllerLayer(layerInex = 0) {
	        return this._controllerLayers[layerInex];
	    }
	    getCurrentAnimatorPlayState(layerInex = 0) {
	        return this._controllerLayers[layerInex]._playStateInfo;
	    }
	    play(name = null, layerIndex = 0, normalizedTime = Number.NEGATIVE_INFINITY) {
	        var controllerLayer = this._controllerLayers[layerIndex];
	        if (controllerLayer) {
	            var defaultState = controllerLayer.defaultState;
	            if (!name && !defaultState)
	                throw new Error("Animator:must have  default clip value,please set clip property.");
	            var curPlayState = controllerLayer._currentPlayState;
	            var playStateInfo = controllerLayer._playStateInfo;
	            var animatorState = name ? controllerLayer._statesMap[name] : defaultState;
	            var clipDuration = animatorState._clip._duration;
	            if (curPlayState !== animatorState) {
	                if (normalizedTime !== Number.NEGATIVE_INFINITY)
	                    playStateInfo._resetPlayState(clipDuration * normalizedTime);
	                else
	                    playStateInfo._resetPlayState(0.0);
	                (curPlayState !== null && curPlayState !== animatorState) && (this._revertDefaultKeyframeNodes(curPlayState));
	                controllerLayer._playType = 0;
	                controllerLayer._currentPlayState = animatorState;
	            }
	            else {
	                if (normalizedTime !== Number.NEGATIVE_INFINITY) {
	                    playStateInfo._resetPlayState(clipDuration * normalizedTime);
	                    controllerLayer._playType = 0;
	                }
	            }
	            var scripts = animatorState._scripts;
	            if (scripts) {
	                for (var i = 0, n = scripts.length; i < n; i++)
	                    scripts[i].onStateEnter();
	            }
	        }
	        else {
	            console.warn("Invalid layerIndex " + layerIndex + ".");
	        }
	    }
	    crossFade(name, transitionDuration, layerIndex = 0, normalizedTime = Number.NEGATIVE_INFINITY) {
	        var controllerLayer = this._controllerLayers[layerIndex];
	        if (controllerLayer) {
	            var destAnimatorState = controllerLayer._statesMap[name];
	            if (destAnimatorState) {
	                var playType = controllerLayer._playType;
	                if (playType === -1) {
	                    this.play(name, layerIndex, normalizedTime);
	                    return;
	                }
	                var crossPlayStateInfo = controllerLayer._crossPlayStateInfo;
	                var crossNodeOwners = controllerLayer._crossNodesOwners;
	                var crossNodeOwnerIndicesMap = controllerLayer._crossNodesOwnersIndicesMap;
	                var srcAnimatorState = controllerLayer._currentPlayState;
	                var destNodeOwners = destAnimatorState._nodeOwners;
	                var destCrossClipNodeIndices = controllerLayer._destCrossClipNodeIndices;
	                var destClip = destAnimatorState._clip;
	                var destNodes = destClip._nodes;
	                var destNodesMap = destClip._nodesDic;
	                switch (playType) {
	                    case 0:
	                        var srcNodeOwners = srcAnimatorState._nodeOwners;
	                        var scrCrossClipNodeIndices = controllerLayer._srcCrossClipNodeIndices;
	                        var srcClip = srcAnimatorState._clip;
	                        var srcNodes = srcClip._nodes;
	                        var srcNodesMap = srcClip._nodesDic;
	                        controllerLayer._playType = 1;
	                        var crossMark = ++controllerLayer._crossMark;
	                        var crossCount = controllerLayer._crossNodesOwnersCount = 0;
	                        for (var i = 0, n = srcNodes.count; i < n; i++) {
	                            var srcNode = srcNodes.getNodeByIndex(i);
	                            var srcIndex = srcNode._indexInList;
	                            var srcNodeOwner = srcNodeOwners[srcIndex];
	                            if (srcNodeOwner) {
	                                var srcFullPath = srcNode.fullPath;
	                                scrCrossClipNodeIndices[crossCount] = srcIndex;
	                                var destNode = destNodesMap[srcFullPath];
	                                if (destNode)
	                                    destCrossClipNodeIndices[crossCount] = destNode._indexInList;
	                                else
	                                    destCrossClipNodeIndices[crossCount] = -1;
	                                crossNodeOwnerIndicesMap[srcFullPath] = crossMark;
	                                crossNodeOwners[crossCount] = srcNodeOwner;
	                                crossCount++;
	                            }
	                        }
	                        for (i = 0, n = destNodes.count; i < n; i++) {
	                            destNode = destNodes.getNodeByIndex(i);
	                            var destIndex = destNode._indexInList;
	                            var destNodeOwner = destNodeOwners[destIndex];
	                            if (destNodeOwner) {
	                                var destFullPath = destNode.fullPath;
	                                if (!srcNodesMap[destFullPath]) {
	                                    scrCrossClipNodeIndices[crossCount] = -1;
	                                    destCrossClipNodeIndices[crossCount] = destIndex;
	                                    crossNodeOwnerIndicesMap[destFullPath] = crossMark;
	                                    crossNodeOwners[crossCount] = destNodeOwner;
	                                    crossCount++;
	                                }
	                            }
	                        }
	                        break;
	                    case 1:
	                    case 2:
	                        controllerLayer._playType = 2;
	                        for (i = 0, n = crossNodeOwners.length; i < n; i++) {
	                            var nodeOwner = crossNodeOwners[i];
	                            nodeOwner.saveCrossFixedValue();
	                            destNode = destNodesMap[nodeOwner.fullPath];
	                            if (destNode)
	                                destCrossClipNodeIndices[i] = destNode._indexInList;
	                            else
	                                destCrossClipNodeIndices[i] = -1;
	                        }
	                        crossCount = controllerLayer._crossNodesOwnersCount;
	                        crossMark = controllerLayer._crossMark;
	                        for (i = 0, n = destNodes.count; i < n; i++) {
	                            destNode = destNodes.getNodeByIndex(i);
	                            destIndex = destNode._indexInList;
	                            destNodeOwner = destNodeOwners[destIndex];
	                            if (destNodeOwner) {
	                                destFullPath = destNode.fullPath;
	                                if (crossNodeOwnerIndicesMap[destFullPath] !== crossMark) {
	                                    destCrossClipNodeIndices[crossCount] = destIndex;
	                                    crossNodeOwnerIndicesMap[destFullPath] = crossMark;
	                                    nodeOwner = destNodeOwners[destIndex];
	                                    crossNodeOwners[crossCount] = nodeOwner;
	                                    nodeOwner.saveCrossFixedValue();
	                                    crossCount++;
	                                }
	                            }
	                        }
	                        break;
	                    default:
	                }
	                controllerLayer._crossNodesOwnersCount = crossCount;
	                controllerLayer._crossPlayState = destAnimatorState;
	                controllerLayer._crossDuration = srcAnimatorState._clip._duration * transitionDuration;
	                if (normalizedTime !== Number.NEGATIVE_INFINITY)
	                    crossPlayStateInfo._resetPlayState(destClip._duration * normalizedTime);
	                else
	                    crossPlayStateInfo._resetPlayState(0.0);
	                var scripts = destAnimatorState._scripts;
	                if (scripts) {
	                    for (i = 0, n = scripts.length; i < n; i++)
	                        scripts[i].onStateEnter();
	                }
	            }
	            else {
	                console.warn("Invalid name " + layerIndex + ".");
	            }
	        }
	        else {
	            console.warn("Invalid layerIndex " + layerIndex + ".");
	        }
	    }
	    get avatar() {
	        return this._avatar;
	    }
	    set avatar(value) {
	        if (this._avatar !== value) {
	            this._avatar = value;
	            if (value) {
	                this._getAvatarOwnersAndInitDatasAsync();
	                this.owner._changeHierarchyAnimatorAvatar(this, value);
	            }
	            else {
	                var parent = this.owner._parent;
	                this.owner._changeHierarchyAnimatorAvatar(this, parent ? parent._hierarchyAnimator._avatar : null);
	            }
	        }
	    }
	    _getAvatarOwnersAndInitDatasAsync() {
	        for (var i = 0, n = this._controllerLayers.length; i < n; i++) {
	            var clipStateInfos = this._controllerLayers[i]._states;
	            for (var j = 0, m = clipStateInfos.length; j < m; j++)
	                this._getOwnersByClip(clipStateInfos[j]);
	        }
	        this._avatar._cloneDatasToAnimator(this);
	        for (var k in this._linkAvatarSpritesData) {
	            var sprites = this._linkAvatarSpritesData[k];
	            if (sprites) {
	                for (var c = 0, p = sprites.length; c < p; c++)
	                    this._isLinkSpriteToAnimationNode(sprites[c], k, true);
	            }
	        }
	    }
	    _isLinkSpriteToAnimationNode(sprite, nodeName, isLink) {
	        if (this._avatar) {
	            var node = this._avatarNodeMap[nodeName];
	            if (node) {
	                if (isLink) {
	                    sprite._transform._dummy = node.transform;
	                    this._linkAvatarSprites.push(sprite);
	                    var nodeTransform = node.transform;
	                    var spriteTransform = sprite.transform;
	                    if (!spriteTransform.owner.isStatic && nodeTransform) {
	                        var spriteWorldMatrix = spriteTransform.worldMatrix;
	                        var ownParTra = this.owner._transform._parent;
	                        if (ownParTra) {
	                            Utils3D.matrix4x4MultiplyMFM(ownParTra.worldMatrix, nodeTransform.getWorldMatrix(), spriteWorldMatrix);
	                        }
	                        else {
	                            var sprWorE = spriteWorldMatrix.elements;
	                            var nodWorE = nodeTransform.getWorldMatrix();
	                            for (var i = 0; i < 16; i++)
	                                sprWorE[i] = nodWorE[i];
	                        }
	                        spriteTransform.worldMatrix = spriteWorldMatrix;
	                    }
	                }
	                else {
	                    sprite._transform._dummy = null;
	                    this._linkAvatarSprites.splice(this._linkAvatarSprites.indexOf(sprite), 1);
	                }
	            }
	        }
	    }
	    _isLinkSpriteToAnimationNodeData(sprite, nodeName, isLink) {
	        var linkSprites = this._linkAvatarSpritesData[nodeName];
	        if (isLink) {
	            linkSprites || (this._linkAvatarSpritesData[nodeName] = linkSprites = []);
	            linkSprites.push(sprite);
	        }
	        else {
	            var index = linkSprites.indexOf(sprite);
	            linkSprites.splice(index, 1);
	        }
	    }
	    _updateAvatarNodesToSprite() {
	        for (var i = 0, n = this._linkAvatarSprites.length; i < n; i++) {
	            var sprite = this._linkAvatarSprites[i];
	            var nodeTransform = sprite.transform._dummy;
	            var spriteTransform = sprite.transform;
	            if (!spriteTransform.owner.isStatic && nodeTransform) {
	                var spriteWorldMatrix = spriteTransform.worldMatrix;
	                var ownTra = this.owner._transform;
	                Utils3D.matrix4x4MultiplyMFM(ownTra.worldMatrix, nodeTransform.getWorldMatrix(), spriteWorldMatrix);
	                spriteTransform.worldMatrix = spriteWorldMatrix;
	            }
	        }
	    }
	    linkSprite3DToAvatarNode(nodeName, sprite3D) {
	        this._isLinkSpriteToAnimationNodeData(sprite3D, nodeName, true);
	        this._isLinkSpriteToAnimationNode(sprite3D, nodeName, true);
	        return true;
	    }
	    unLinkSprite3DToAvatarNode(sprite3D) {
	        if (sprite3D._hierarchyAnimator === this) {
	            var dummy = sprite3D.transform._dummy;
	            if (dummy) {
	                var nodeName = dummy._owner.name;
	                this._isLinkSpriteToAnimationNodeData(sprite3D, nodeName, false);
	                this._isLinkSpriteToAnimationNode(sprite3D, nodeName, false);
	                return true;
	            }
	            else {
	                return false;
	            }
	        }
	        else {
	            throw ("Animator:sprite3D must belong to this Animator");
	            return false;
	        }
	    }
	    _updateAnimationNodeWorldMatix(localPositions, localRotations, localScales, worldMatrixs, parentIndices) {
	        Laya.LayaGL.instance.updateAnimationNodeWorldMatix(localPositions, localRotations, localScales, parentIndices, worldMatrixs);
	    }
	}
	Animator._tempVector30 = new Vector3();
	Animator._tempVector31 = new Vector3();
	Animator._tempQuaternion0 = new Quaternion();
	Animator._tempQuaternion1 = new Quaternion();
	Animator.CULLINGMODE_ALWAYSANIMATE = 0;
	Animator.CULLINGMODE_CULLCOMPLETELY = 2;

	class PostProcessRenderContext {
	    constructor() {
	        this.source = null;
	        this.destination = null;
	        this.camera = null;
	        this.compositeShaderData = null;
	        this.command = null;
	        this.deferredReleaseTextures = [];
	    }
	}

	class RenderContext3D {
	    constructor() {
	    }
	}
	RenderContext3D._instance = new RenderContext3D();

	class RenderTexture extends Laya.BaseTexture {
	    constructor(width, height, format = Laya.RenderTextureFormat.R8G8B8, depthStencilFormat = Laya.RenderTextureDepthFormat.DEPTH_16) {
	        super(format, false);
	        this._inPool = false;
	        this._glTextureType = Laya.LayaGL.instance.TEXTURE_2D;
	        this._width = width;
	        this._height = height;
	        this._depthStencilFormat = depthStencilFormat;
	        this._create(width, height);
	    }
	    static get currentActive() {
	        return RenderTexture._currentActive;
	    }
	    static createFromPool(width, height, format = Laya.RenderTextureFormat.R8G8B8, depthStencilFormat = Laya.RenderTextureDepthFormat.DEPTH_16, filterMode = Laya.BaseTexture.FILTERMODE_BILINEAR) {
	        var tex;
	        for (var i = 0, n = RenderTexture._pool.length; i < n; i++) {
	            tex = RenderTexture._pool[i];
	            if (tex._width == width && tex._height == height && tex._format == format && tex._depthStencilFormat == depthStencilFormat && tex._filterMode == filterMode) {
	                tex._inPool = false;
	                var end = RenderTexture._pool[n - 1];
	                RenderTexture._pool[i] = end;
	                RenderTexture._pool.length -= 1;
	                return tex;
	            }
	        }
	        tex = new RenderTexture(width, height, format, depthStencilFormat);
	        tex.filterMode = filterMode;
	        tex.lock = true;
	        return tex;
	    }
	    static recoverToPool(renderTexture) {
	        if (renderTexture._inPool)
	            return;
	        RenderTexture._pool.push(renderTexture);
	        renderTexture._inPool = true;
	    }
	    get depthStencilFormat() {
	        return this._depthStencilFormat;
	    }
	    get defaulteTexture() {
	        return Laya.Texture2D.grayTexture;
	    }
	    _texImage2D(gl, glTextureType, width, height) {
	        switch (this._format) {
	            case Laya.RenderTextureFormat.R8G8B8:
	                gl.texImage2D(glTextureType, 0, gl.RGB, width, height, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
	                break;
	            case Laya.RenderTextureFormat.R8G8B8A8:
	                gl.texImage2D(glTextureType, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
	                break;
	            case Laya.RenderTextureFormat.Alpha8:
	                gl.texImage2D(glTextureType, 0, gl.ALPHA, width, height, 0, gl.ALPHA, gl.UNSIGNED_BYTE, null);
	                break;
	            case Laya.RenderTextureFormat.R16G16B16A16:
	                if (Laya.LayaGL.layaGPUInstance._isWebGL2)
	                    gl.texImage2D(this._glTextureType, 0, gl.RGBA16F, width, height, 0, gl.RGBA, gl.HALF_FLOAT, null);
	                else
	                    gl.texImage2D(this._glTextureType, 0, gl.RGBA, width, height, 0, gl.RGBA, Laya.LayaGL.layaGPUInstance._oesTextureHalfFloat.HALF_FLOAT_OES, null);
	                break;
	            default:
	                break;
	        }
	    }
	    _create(width, height) {
	        var gl = Laya.LayaGL.instance;
	        this._frameBuffer = gl.createFramebuffer();
	        Laya.WebGLContext.bindTexture(gl, this._glTextureType, this._glTexture);
	        this._texImage2D(gl, this._glTextureType, width, height);
	        this._setGPUMemory(width * height * 4);
	        gl.bindFramebuffer(gl.FRAMEBUFFER, this._frameBuffer);
	        gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this._glTexture, 0);
	        if (this._depthStencilFormat !== Laya.RenderTextureDepthFormat.DEPTHSTENCIL_NONE) {
	            this._depthStencilBuffer = gl.createRenderbuffer();
	            gl.bindRenderbuffer(gl.RENDERBUFFER, this._depthStencilBuffer);
	            switch (this._depthStencilFormat) {
	                case Laya.RenderTextureDepthFormat.DEPTH_16:
	                    gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, width, height);
	                    gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, this._depthStencilBuffer);
	                    break;
	                case Laya.RenderTextureDepthFormat.STENCIL_8:
	                    gl.renderbufferStorage(gl.RENDERBUFFER, gl.STENCIL_INDEX8, width, height);
	                    gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, this._depthStencilBuffer);
	                    break;
	                case Laya.RenderTextureDepthFormat.DEPTHSTENCIL_16_8:
	                    gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height);
	                    gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, this._depthStencilBuffer);
	                    break;
	                default:
	                    throw "RenderTexture: unkonw depth format.";
	            }
	        }
	        gl.bindFramebuffer(gl.FRAMEBUFFER, null);
	        gl.bindRenderbuffer(gl.RENDERBUFFER, null);
	        this._setWarpMode(gl.TEXTURE_WRAP_S, this._wrapModeU);
	        this._setWarpMode(gl.TEXTURE_WRAP_T, this._wrapModeV);
	        this._setFilterMode(this._filterMode);
	        this._setAnisotropy(this._anisoLevel);
	        this._readyed = true;
	        this._activeResource();
	    }
	    _start() {
	        var gl = Laya.LayaGL.instance;
	        gl.bindFramebuffer(gl.FRAMEBUFFER, this._frameBuffer);
	        RenderTexture._currentActive = this;
	        this._readyed = false;
	    }
	    _end() {
	        var gl = Laya.LayaGL.instance;
	        gl.bindFramebuffer(gl.FRAMEBUFFER, null);
	        RenderTexture._currentActive = null;
	        this._readyed = true;
	    }
	    getData(x, y, width, height, out) {
	        if (Laya.Render.isConchApp && window.conchConfig.threadMode == 2) {
	            throw "native 2 thread mode use getDataAsync";
	        }
	        var gl = Laya.LayaGL.instance;
	        gl.bindFramebuffer(gl.FRAMEBUFFER, this._frameBuffer);
	        var canRead = (gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE);
	        if (!canRead) {
	            gl.bindFramebuffer(gl.FRAMEBUFFER, null);
	            return null;
	        }
	        gl.readPixels(x, y, width, height, gl.RGBA, gl.UNSIGNED_BYTE, out);
	        gl.bindFramebuffer(gl.FRAMEBUFFER, null);
	        return out;
	    }
	    getDataAsync(x, y, width, height, callBack) {
	        var gl = Laya.LayaGL.instance;
	        gl.bindFramebuffer(gl.FRAMEBUFFER, this._frameBuffer);
	        gl.readPixelsAsync(x, y, width, height, gl.RGBA, gl.UNSIGNED_BYTE, function (data) {
	            callBack(new Uint8Array(data));
	        });
	        gl.bindFramebuffer(gl.FRAMEBUFFER, null);
	    }
	    _disposeResource() {
	        if (this._frameBuffer) {
	            var gl = Laya.LayaGL.instance;
	            gl.deleteTexture(this._glTexture);
	            gl.deleteFramebuffer(this._frameBuffer);
	            gl.deleteRenderbuffer(this._depthStencilBuffer);
	            this._glTexture = null;
	            this._frameBuffer = null;
	            this._depthStencilBuffer = null;
	            this._setGPUMemory(0);
	        }
	    }
	}
	RenderTexture._pool = [];

	class DefineDatas {
	    constructor() {
	        this._mask = [];
	        this._length = 0;
	    }
	    _intersectionDefineDatas(define) {
	        var unionMask = define._mask;
	        var mask = this._mask;
	        for (var i = this._length - 1; i >= 0; i--) {
	            var value = mask[i] & unionMask[i];
	            if (value == 0 && i == this._length - 1)
	                this._length--;
	            else
	                mask[i] = value;
	        }
	    }
	    add(define) {
	        var index = define._index;
	        var size = index + 1;
	        var mask = this._mask;
	        var maskStart = mask.length;
	        if (maskStart < size) {
	            mask.length = size;
	            for (; maskStart < index; maskStart++)
	                mask[maskStart] = 0;
	            mask[index] = define._value;
	            this._length = size;
	        }
	        else {
	            if (size > this._length) {
	                mask[index] = define._value;
	                this._length = size;
	            }
	            else {
	                mask[index] |= define._value;
	            }
	        }
	    }
	    remove(define) {
	        var index = define._index;
	        var mask = this._mask;
	        var endIndex = this._length - 1;
	        if (index > endIndex)
	            return;
	        var newValue = mask[index] & ~define._value;
	        if (index == endIndex && newValue === 0)
	            this._length--;
	        else
	            mask[index] = newValue;
	    }
	    addDefineDatas(define) {
	        var addMask = define._mask;
	        var size = define._length;
	        var mask = this._mask;
	        var maskStart = mask.length;
	        if (maskStart < size) {
	            mask.length = size;
	            for (var i = 0; i < maskStart; i++)
	                mask[i] |= addMask[i];
	            for (; maskStart < size; maskStart++)
	                mask[maskStart] = addMask[maskStart];
	            this._length = size;
	        }
	        else {
	            for (var i = 0; i < size; i++)
	                mask[i] |= addMask[i];
	            this._length = Math.max(this._length, size);
	        }
	    }
	    removeDefineDatas(define) {
	        var removeMask = define._mask;
	        var mask = this._mask;
	        var endIndex = this._length - 1;
	        for (var i = define._length - 1; i >= 0; i--) {
	            if (i > endIndex)
	                continue;
	            var newValue = mask[i] & ~removeMask[i];
	            if (i == endIndex && newValue === 0) {
	                endIndex--;
	                this._length--;
	            }
	            else {
	                mask[i] = newValue;
	            }
	        }
	    }
	    has(define) {
	        var index = define._index;
	        if (index >= this._length)
	            return false;
	        return (this._mask[index] & define._value) !== 0;
	    }
	    clear() {
	        this._length = 0;
	    }
	    cloneTo(destObject) {
	        var destDefineData = destObject;
	        var destMask = destDefineData._mask;
	        var mask = this._mask;
	        var count = this._length;
	        destMask.length = count;
	        for (var i = 0; i < count; i++)
	            destMask[i] = mask[i];
	        destDefineData._length = count;
	    }
	    clone() {
	        var dest = new DefineDatas();
	        this.cloneTo(dest);
	        return dest;
	    }
	}

	class ShaderDefine {
	    constructor(index, value) {
	        this._index = index;
	        this._value = value;
	    }
	}

	class Shader3D {
	    constructor(name, attributeMap, uniformMap, enableInstancing) {
	        this._attributeMap = null;
	        this._uniformMap = null;
	        this._enableInstancing = false;
	        this._subShaders = [];
	        this._name = name;
	        this._attributeMap = attributeMap;
	        this._uniformMap = uniformMap;
	        this._enableInstancing = enableInstancing;
	    }
	    static _getNamesByDefineData(defineData, out) {
	        var maskMap = Shader3D._maskMap;
	        var mask = defineData._mask;
	        out.length = 0;
	        for (var i = 0, n = defineData._length; i < n; i++) {
	            var subMaskMap = maskMap[i];
	            var subMask = mask[i];
	            for (var j = 0; j < 32; j++) {
	                var d = 1 << j;
	                if (subMask > 0 && d > subMask)
	                    break;
	                if (subMask & d)
	                    out.push(subMaskMap[d]);
	            }
	        }
	    }
	    static getDefineByName(name) {
	        var define = Shader3D._defineMap[name];
	        if (!define) {
	            var maskMap = Shader3D._maskMap;
	            var counter = Shader3D._defineCounter;
	            var index = Math.floor(counter / 32);
	            var value = 1 << counter % 32;
	            define = new ShaderDefine(index, value);
	            Shader3D._defineMap[name] = define;
	            if (index == maskMap.length) {
	                maskMap.length++;
	                maskMap[index] = {};
	            }
	            maskMap[index][value] = name;
	            Shader3D._defineCounter++;
	        }
	        return define;
	    }
	    static propertyNameToID(name) {
	        if (Shader3D._propertyNameMap[name] != null) {
	            return Shader3D._propertyNameMap[name];
	        }
	        else {
	            var id = Shader3D._propertyNameCounter++;
	            Shader3D._propertyNameMap[name] = id;
	            return id;
	        }
	    }
	    static addInclude(fileName, txt) {
	        txt = txt.replace(Laya.ShaderCompile._clearCR, "");
	        Laya.ShaderCompile.addInclude(fileName, txt);
	    }
	    static compileShaderByDefineNames(shaderName, subShaderIndex, passIndex, defineNames) {
	        var shader = Shader3D.find(shaderName);
	        if (shader) {
	            var subShader = shader.getSubShaderAt(subShaderIndex);
	            if (subShader) {
	                var pass = subShader._passes[passIndex];
	                if (pass) {
	                    var compileDefineDatas = Shader3D._compileDefineDatas;
	                    compileDefineDatas.clear();
	                    for (var i = 0, n = defineNames.length; i < n; i++)
	                        compileDefineDatas.add(Shader3D.getDefineByName(defineNames[i]));
	                    (Laya.WebGL.shaderHighPrecision) && (compileDefineDatas.add(Shader3D.SHADERDEFINE_HIGHPRECISION));
	                    (Config3D._config._multiLighting) || (compileDefineDatas.add(Shader3D.SHADERDEFINE_LEGACYSINGALLIGHTING));
	                    pass.withCompile(compileDefineDatas);
	                }
	                else {
	                    console.warn("Shader3D: unknown passIndex.");
	                }
	            }
	            else {
	                console.warn("Shader3D: unknown subShaderIndex.");
	            }
	        }
	        else {
	            console.warn("Shader3D: unknown shader name.");
	        }
	    }
	    static compileShader(shaderName, subShaderIndex, passIndex, ...defineMask) {
	        var shader = Shader3D.find(shaderName);
	        if (shader) {
	            var subShader = shader.getSubShaderAt(subShaderIndex);
	            if (subShader) {
	                var pass = subShader._passes[passIndex];
	                if (pass) {
	                    var compileDefineDatas = Shader3D._compileDefineDatas;
	                    var mask = compileDefineDatas._mask;
	                    mask.length = 0;
	                    for (var i = 0, n = defineMask.length; i < n; i++)
	                        mask.push(defineMask[i]);
	                    compileDefineDatas._length = defineMask.length;
	                    (Laya.WebGL.shaderHighPrecision) && (compileDefineDatas.add(Shader3D.SHADERDEFINE_HIGHPRECISION));
	                    (Config3D._config._multiLighting) || (compileDefineDatas.add(Shader3D.SHADERDEFINE_LEGACYSINGALLIGHTING));
	                    pass.withCompile(compileDefineDatas);
	                }
	                else {
	                    console.warn("Shader3D: unknown passIndex.");
	                }
	            }
	            else {
	                console.warn("Shader3D: unknown subShaderIndex.");
	            }
	        }
	        else {
	            console.warn("Shader3D: unknown shader name.");
	        }
	    }
	    static add(name, attributeMap = null, uniformMap = null, enableInstancing = false) {
	        return Shader3D._preCompileShader[name] = new Shader3D(name, attributeMap, uniformMap, enableInstancing);
	    }
	    static find(name) {
	        return Shader3D._preCompileShader[name];
	    }
	    addSubShader(subShader) {
	        this._subShaders.push(subShader);
	        subShader._owner = this;
	    }
	    getSubShaderAt(index) {
	        return this._subShaders[index];
	    }
	}
	Shader3D._compileDefineDatas = new DefineDatas();
	Shader3D.RENDER_STATE_CULL = 0;
	Shader3D.RENDER_STATE_BLEND = 1;
	Shader3D.RENDER_STATE_BLEND_SRC = 2;
	Shader3D.RENDER_STATE_BLEND_DST = 3;
	Shader3D.RENDER_STATE_BLEND_SRC_RGB = 4;
	Shader3D.RENDER_STATE_BLEND_DST_RGB = 5;
	Shader3D.RENDER_STATE_BLEND_SRC_ALPHA = 6;
	Shader3D.RENDER_STATE_BLEND_DST_ALPHA = 7;
	Shader3D.RENDER_STATE_BLEND_CONST_COLOR = 8;
	Shader3D.RENDER_STATE_BLEND_EQUATION = 9;
	Shader3D.RENDER_STATE_BLEND_EQUATION_RGB = 10;
	Shader3D.RENDER_STATE_BLEND_EQUATION_ALPHA = 11;
	Shader3D.RENDER_STATE_DEPTH_TEST = 12;
	Shader3D.RENDER_STATE_DEPTH_WRITE = 13;
	Shader3D.PERIOD_CUSTOM = 0;
	Shader3D.PERIOD_MATERIAL = 1;
	Shader3D.PERIOD_SPRITE = 2;
	Shader3D.PERIOD_CAMERA = 3;
	Shader3D.PERIOD_SCENE = 4;
	Shader3D._propertyNameCounter = 0;
	Shader3D._propertyNameMap = {};
	Shader3D._defineCounter = 0;
	Shader3D._defineMap = {};
	Shader3D._preCompileShader = {};
	Shader3D._maskMap = [];
	Shader3D.debugMode = true;

	class ShaderData {
	    constructor(ownerResource = null) {
	        this._ownerResource = null;
	        this._data = null;
	        this._defineDatas = new DefineDatas();
	        this._runtimeCopyValues = [];
	        this._ownerResource = ownerResource;
	        this._initData();
	    }
	    _initData() {
	        this._data = new Object();
	    }
	    getData() {
	        return this._data;
	    }
	    addDefine(define) {
	        this._defineDatas.add(define);
	    }
	    removeDefine(define) {
	        this._defineDatas.remove(define);
	    }
	    hasDefine(define) {
	        return this._defineDatas.has(define);
	    }
	    clearDefine() {
	        this._defineDatas.clear();
	    }
	    getBool(index) {
	        return this._data[index];
	    }
	    setBool(index, value) {
	        this._data[index] = value;
	    }
	    getInt(index) {
	        return this._data[index];
	    }
	    setInt(index, value) {
	        this._data[index] = value;
	    }
	    getNumber(index) {
	        return this._data[index];
	    }
	    setNumber(index, value) {
	        this._data[index] = value;
	    }
	    getVector2(index) {
	        return this._data[index];
	    }
	    setVector2(index, value) {
	        this._data[index] = value;
	    }
	    getVector3(index) {
	        return this._data[index];
	    }
	    setVector3(index, value) {
	        this._data[index] = value;
	    }
	    getVector(index) {
	        return this._data[index];
	    }
	    setVector(index, value) {
	        this._data[index] = value;
	    }
	    getQuaternion(index) {
	        return this._data[index];
	    }
	    setQuaternion(index, value) {
	        this._data[index] = value;
	    }
	    getMatrix4x4(index) {
	        return this._data[index];
	    }
	    setMatrix4x4(index, value) {
	        this._data[index] = value;
	    }
	    getBuffer(shaderIndex) {
	        return this._data[shaderIndex];
	    }
	    setBuffer(index, value) {
	        this._data[index] = value;
	    }
	    setTexture(index, value) {
	        var lastValue = this._data[index];
	        this._data[index] = value;
	        if (this._ownerResource && this._ownerResource.referenceCount > 0) {
	            (lastValue) && (lastValue._removeReference());
	            (value) && (value._addReference());
	        }
	    }
	    getTexture(index) {
	        return this._data[index];
	    }
	    setAttribute(index, value) {
	        this._data[index] = value;
	    }
	    getAttribute(index) {
	        return this._data[index];
	    }
	    getLength() {
	        return this._data.length;
	    }
	    setLength(value) {
	        this._data.length = value;
	    }
	    cloneTo(destObject) {
	        var dest = destObject;
	        var destData = dest._data;
	        for (var k in this._data) {
	            var value = this._data[k];
	            if (value != null) {
	                if (typeof (value) == 'number') {
	                    destData[k] = value;
	                }
	                else if (typeof (value) == 'number') {
	                    destData[k] = value;
	                }
	                else if (typeof (value) == "boolean") {
	                    destData[k] = value;
	                }
	                else if (value instanceof Vector2) {
	                    var v2 = (destData[k]) || (destData[k] = new Vector2());
	                    value.cloneTo(v2);
	                    destData[k] = v2;
	                }
	                else if (value instanceof Vector3) {
	                    var v3 = (destData[k]) || (destData[k] = new Vector3());
	                    value.cloneTo(v3);
	                    destData[k] = v3;
	                }
	                else if (value instanceof Vector4) {
	                    var v4 = (destData[k]) || (destData[k] = new Vector4());
	                    value.cloneTo(v4);
	                    destData[k] = v4;
	                }
	                else if (value instanceof Matrix4x4) {
	                    var mat = (destData[k]) || (destData[k] = new Matrix4x4());
	                    value.cloneTo(mat);
	                    destData[k] = mat;
	                }
	                else if (value instanceof Laya.BaseTexture) {
	                    destData[k] = value;
	                }
	            }
	        }
	        this._defineDatas.cloneTo(dest._defineDatas);
	    }
	    clone() {
	        var dest = new ShaderData();
	        this.cloneTo(dest);
	        return dest;
	    }
	    cloneToForNative(destObject) {
	        var dest = destObject;
	        var diffSize = this._int32Data.length - dest._int32Data.length;
	        if (diffSize > 0) {
	            dest.needRenewArrayBufferForNative(this._int32Data.length);
	        }
	        dest._int32Data.set(this._int32Data, 0);
	        var destData = dest._nativeArray;
	        var dataCount = this._nativeArray.length;
	        destData.length = dataCount;
	        for (var i = 0; i < dataCount; i++) {
	            var value = this._nativeArray[i];
	            if (value) {
	                if (typeof (value) == 'number') {
	                    destData[i] = value;
	                    dest.setNumber(i, value);
	                }
	                else if (typeof (value) == 'number') {
	                    destData[i] = value;
	                    dest.setInt(i, value);
	                }
	                else if (typeof (value) == "boolean") {
	                    destData[i] = value;
	                    dest.setBool(i, value);
	                }
	                else if (value instanceof Vector2) {
	                    var v2 = (destData[i]) || (destData[i] = new Vector2());
	                    value.cloneTo(v2);
	                    destData[i] = v2;
	                    dest.setVector2(i, v2);
	                }
	                else if (value instanceof Vector3) {
	                    var v3 = (destData[i]) || (destData[i] = new Vector3());
	                    value.cloneTo(v3);
	                    destData[i] = v3;
	                    dest.setVector3(i, v3);
	                }
	                else if (value instanceof Vector4) {
	                    var v4 = (destData[i]) || (destData[i] = new Vector4());
	                    value.cloneTo(v4);
	                    destData[i] = v4;
	                    dest.setVector(i, v4);
	                }
	                else if (value instanceof Matrix4x4) {
	                    var mat = (destData[i]) || (destData[i] = new Matrix4x4());
	                    value.cloneTo(mat);
	                    destData[i] = mat;
	                    dest.setMatrix4x4(i, mat);
	                }
	                else if (value instanceof Laya.BaseTexture) {
	                    destData[i] = value;
	                    dest.setTexture(i, value);
	                }
	            }
	        }
	        this._defineDatas.cloneTo(dest._defineDatas);
	    }
	    _initDataForNative() {
	        var length = 8;
	        this._frameCount = -1;
	        this._runtimeCopyValues.length = 0;
	        this._nativeArray = [];
	        this._data = new ArrayBuffer(length * 4);
	        this._int32Data = new Int32Array(this._data);
	        this._float32Data = new Float32Array(this._data);
	        Laya.LayaGL.instance.createArrayBufferRef(this._data, Laya.LayaGL.ARRAY_BUFFER_TYPE_DATA, true);
	    }
	    needRenewArrayBufferForNative(index) {
	        if (index >= this._int32Data.length) {
	            var nByteLen = (index + 1) * 4;
	            var pre = this._int32Data;
	            var preConchRef = this._data["conchRef"];
	            var prePtrID = this._data["_ptrID"];
	            this._data = new ArrayBuffer(nByteLen);
	            this._int32Data = new Int32Array(this._data);
	            this._float32Data = new Float32Array(this._data);
	            this._data["conchRef"] = preConchRef;
	            this._data["_ptrID"] = prePtrID;
	            pre && this._int32Data.set(pre, 0);
	            var layagl = Laya.LayaGL.instance;
	            if (layagl.updateArrayBufferRef) {
	                layagl.updateArrayBufferRef(this._data['_ptrID'], preConchRef.isSyncToRender(), this._data);
	            }
	            else {
	                window.conch.updateArrayBufferRef(this._data['_ptrID'], preConchRef.isSyncToRender(), this._data);
	            }
	        }
	    }
	    getDataForNative() {
	        return this._nativeArray;
	    }
	    getIntForNative(index) {
	        return this._int32Data[index];
	    }
	    setIntForNative(index, value) {
	        this.needRenewArrayBufferForNative(index);
	        this._int32Data[index] = value;
	        this._nativeArray[index] = value;
	    }
	    getBoolForNative(index) {
	        return this._int32Data[index] == 1;
	    }
	    setBoolForNative(index, value) {
	        this.needRenewArrayBufferForNative(index);
	        this._int32Data[index] = value ? 1 : 0;
	        this._nativeArray[index] = value;
	    }
	    getNumberForNative(index) {
	        return this._float32Data[index];
	    }
	    setNumberForNative(index, value) {
	        this.needRenewArrayBufferForNative(index);
	        this._float32Data[index] = value;
	        this._nativeArray[index] = value;
	    }
	    getMatrix4x4ForNative(index) {
	        return this._nativeArray[index];
	    }
	    setMatrix4x4ForNative(index, value) {
	        this.needRenewArrayBufferForNative(index);
	        this._nativeArray[index] = value;
	        var nPtrID = this.setReferenceForNative(value.elements);
	        this._int32Data[index] = nPtrID;
	    }
	    getVectorForNative(index) {
	        return this._nativeArray[index];
	    }
	    setVectorForNative(index, value) {
	        this.needRenewArrayBufferForNative(index);
	        this._nativeArray[index] = value;
	        if (!value.elements) {
	            value.forNativeElement();
	        }
	        var nPtrID = this.setReferenceForNative(value.elements);
	        this._int32Data[index] = nPtrID;
	    }
	    getVector2ForNative(index) {
	        return this._nativeArray[index];
	    }
	    setVector2ForNative(index, value) {
	        this.needRenewArrayBufferForNative(index);
	        this._nativeArray[index] = value;
	        if (!value.elements) {
	            value.forNativeElement();
	        }
	        var nPtrID = this.setReferenceForNative(value.elements);
	        this._int32Data[index] = nPtrID;
	    }
	    getVector3ForNative(index) {
	        return this._nativeArray[index];
	    }
	    setVector3ForNative(index, value) {
	        this.needRenewArrayBufferForNative(index);
	        this._nativeArray[index] = value;
	        if (!value.elements) {
	            value.forNativeElement();
	        }
	        var nPtrID = this.setReferenceForNative(value.elements);
	        this._int32Data[index] = nPtrID;
	    }
	    getQuaternionForNative(index) {
	        return this._nativeArray[index];
	    }
	    setQuaternionForNative(index, value) {
	        this.needRenewArrayBufferForNative(index);
	        this._nativeArray[index] = value;
	        if (!value.elements) {
	            value.forNativeElement();
	        }
	        var nPtrID = this.setReferenceForNative(value.elements);
	        this._int32Data[index] = nPtrID;
	    }
	    getBufferForNative(shaderIndex) {
	        return this._nativeArray[shaderIndex];
	    }
	    setBufferForNative(index, value) {
	        this.needRenewArrayBufferForNative(index);
	        this._nativeArray[index] = value;
	        var nPtrID = this.setReferenceForNative(value);
	        this._int32Data[index] = nPtrID;
	    }
	    getAttributeForNative(index) {
	        return this._nativeArray[index];
	    }
	    setAttributeForNative(index, value) {
	        this._nativeArray[index] = value;
	        if (!value["_ptrID"]) {
	            Laya.LayaGL.instance.createArrayBufferRef(value, Laya.LayaGL.ARRAY_BUFFER_TYPE_DATA, true);
	        }
	        Laya.LayaGL.instance.syncBufferToRenderThread(value);
	        this._int32Data[index] = value["_ptrID"];
	    }
	    getTextureForNative(index) {
	        return this._nativeArray[index];
	    }
	    setTextureForNative(index, value) {
	        if (!value)
	            return;
	        this.needRenewArrayBufferForNative(index);
	        var lastValue = this._nativeArray[index];
	        this._nativeArray[index] = value;
	        var glTexture = value._getSource() || value.defaulteTexture._getSource();
	        this._int32Data[index] = glTexture.id;
	        if (this._ownerResource && this._ownerResource.referenceCount > 0) {
	            (lastValue) && (lastValue._removeReference());
	            (value) && (value._addReference());
	        }
	    }
	    setReferenceForNative(value) {
	        this.clearRuntimeCopyArray();
	        var nRefID = 0;
	        var nPtrID = 0;
	        if (ShaderData._SET_RUNTIME_VALUE_MODE_REFERENCE_) {
	            Laya.LayaGL.instance.createArrayBufferRefs(value, Laya.LayaGL.ARRAY_BUFFER_TYPE_DATA, true, Laya.LayaGL.ARRAY_BUFFER_REF_REFERENCE);
	            nRefID = 0;
	            nPtrID = value.getPtrID(nRefID);
	        }
	        else {
	            Laya.LayaGL.instance.createArrayBufferRefs(value, Laya.LayaGL.ARRAY_BUFFER_TYPE_DATA, true, Laya.LayaGL.ARRAY_BUFFER_REF_COPY);
	            nRefID = value.getRefNum() - 1;
	            nPtrID = value.getPtrID(nRefID);
	            this._runtimeCopyValues.push({ "obj": value, "refID": nRefID, "ptrID": nPtrID });
	        }
	        Laya.LayaGL.instance.syncBufferToRenderThread(value, nRefID);
	        return nPtrID;
	    }
	    static setRuntimeValueMode(bReference) {
	        ShaderData._SET_RUNTIME_VALUE_MODE_REFERENCE_ = bReference;
	    }
	    clearRuntimeCopyArray() {
	        var currentFrame = Laya.Stat.loopCount;
	        if (this._frameCount != currentFrame) {
	            this._frameCount = currentFrame;
	            for (var i = 0, n = this._runtimeCopyValues.length; i < n; i++) {
	                var obj = this._runtimeCopyValues[i];
	                obj.obj.clearRefNum();
	            }
	            this._runtimeCopyValues.length = 0;
	        }
	    }
	}
	ShaderData._SET_RUNTIME_VALUE_MODE_REFERENCE_ = true;

	class PostProcess {
	    constructor() {
	        this._compositeShader = Shader3D.find("PostProcessComposite");
	        this._compositeShaderData = new ShaderData();
	        this._context = null;
	        this._effects = [];
	        this._context = new PostProcessRenderContext();
	        this._context.compositeShaderData = this._compositeShaderData;
	    }
	    static __init__() {
	        PostProcess.SHADERDEFINE_BLOOM_LOW = Shader3D.getDefineByName("BLOOM_LOW");
	        PostProcess.SHADERDEFINE_BLOOM = Shader3D.getDefineByName("BLOOM");
	        PostProcess.SHADERDEFINE_FINALPASS = Shader3D.getDefineByName("FINALPASS");
	    }
	    _init(camera, command) {
	        this._context.camera = camera;
	        this._context.command = command;
	    }
	    _render() {
	        var noteValue = ShaderData._SET_RUNTIME_VALUE_MODE_REFERENCE_;
	        Laya.ILaya.Render.supportWebGLPlusRendering && ShaderData.setRuntimeValueMode(false);
	        var camera = this._context.camera;
	        var screenTexture = RenderTexture.createFromPool(RenderContext3D.clientWidth, RenderContext3D.clientHeight, camera._getRenderTextureFormat(), Laya.RenderTextureDepthFormat.DEPTHSTENCIL_NONE);
	        var cameraTarget = camera._renderTexture;
	        this._context.command.clear();
	        this._context.source = screenTexture;
	        this._context.destination = cameraTarget;
	        this._context.compositeShaderData.clearDefine();
	        this._context.command.blitScreenTriangle(cameraTarget, screenTexture);
	        this._context.compositeShaderData.setTexture(PostProcess.SHADERVALUE_AUTOEXPOSURETEX, Laya.Texture2D.whiteTexture);
	        for (var i = 0, n = this._effects.length; i < n; i++)
	            this._effects[i].render(this._context);
	        this._compositeShaderData.addDefine(PostProcess.SHADERDEFINE_FINALPASS);
	        var offScreenTexture = camera.renderTarget;
	        var dest = offScreenTexture ? offScreenTexture : null;
	        this._context.destination = dest;
	        this._context.command.blitScreenTriangle(this._context.source, dest, this._compositeShader, this._compositeShaderData);
	        RenderTexture.recoverToPool(screenTexture);
	        var tempRenderTextures = this._context.deferredReleaseTextures;
	        for (i = 0, n = tempRenderTextures.length; i < n; i++)
	            RenderTexture.recoverToPool(tempRenderTextures[i]);
	        tempRenderTextures.length = 0;
	        Laya.ILaya.Render.supportWebGLPlusRendering && ShaderData.setRuntimeValueMode(noteValue);
	    }
	    addEffect(effect) {
	        this._effects.push(effect);
	    }
	    removeEffect(effect) {
	        var index = this._effects.indexOf(effect);
	        if (index !== -1)
	            this._effects.splice(index, 1);
	    }
	}
	PostProcess.SHADERVALUE_MAINTEX = Shader3D.propertyNameToID("u_MainTex");
	PostProcess.SHADERVALUE_BLOOMTEX = Shader3D.propertyNameToID("u_BloomTex");
	PostProcess.SHADERVALUE_AUTOEXPOSURETEX = Shader3D.propertyNameToID("u_AutoExposureTex");
	PostProcess.SHADERVALUE_BLOOM_DIRTTEX = Shader3D.propertyNameToID("u_Bloom_DirtTex");
	PostProcess.SHADERVALUE_BLOOMTEX_TEXELSIZE = Shader3D.propertyNameToID("u_BloomTex_TexelSize");
	PostProcess.SHADERVALUE_BLOOM_DIRTTILEOFFSET = Shader3D.propertyNameToID("u_Bloom_DirtTileOffset");
	PostProcess.SHADERVALUE_BLOOM_SETTINGS = Shader3D.propertyNameToID("u_Bloom_Settings");
	PostProcess.SHADERVALUE_BLOOM_COLOR = Shader3D.propertyNameToID("u_Bloom_Color");

	class AnimationTransform3D extends Laya.EventDispatcher {
	    constructor(owner, localPosition = null, localRotation = null, localScale = null, worldMatrix = null) {
	        super();
	        this._owner = owner;
	        this._children = [];
	        this._localMatrix = new Float32Array(16);
	        if (Laya.Render.supportWebGLPlusAnimation) {
	            this._localPosition = new ConchVector3(0, 0, 0, localPosition);
	            this._localRotation = new ConchQuaternion(0, 0, 0, 1, localRotation);
	            this._localScale = new ConchVector3(0, 0, 0, localScale);
	            this._worldMatrix = worldMatrix;
	        }
	        else {
	            this._localPosition = new Vector3();
	            this._localRotation = new Quaternion();
	            this._localScale = new Vector3();
	            this._worldMatrix = new Float32Array(16);
	        }
	        this._localQuaternionUpdate = false;
	        this._locaEulerlUpdate = false;
	        this._localUpdate = false;
	        this._worldUpdate = true;
	    }
	    _getlocalMatrix() {
	        if (this._localUpdate) {
	            Utils3D._createAffineTransformationArray(this._localPosition, this._localRotation, this._localScale, this._localMatrix);
	            this._localUpdate = false;
	        }
	        return this._localMatrix;
	    }
	    _onWorldTransform() {
	        if (!this._worldUpdate) {
	            this._worldUpdate = true;
	            this.event(Laya.Event.TRANSFORM_CHANGED);
	            for (var i = 0, n = this._children.length; i < n; i++)
	                this._children[i]._onWorldTransform();
	        }
	    }
	    get localPosition() {
	        return this._localPosition;
	    }
	    set localPosition(value) {
	        this._localPosition = value;
	        this._localUpdate = true;
	        this._onWorldTransform();
	    }
	    get localRotation() {
	        if (this._localQuaternionUpdate) {
	            var euler = this._localRotationEuler;
	            Quaternion.createFromYawPitchRoll(euler.y / AnimationTransform3D._angleToRandin, euler.x / AnimationTransform3D._angleToRandin, euler.z / AnimationTransform3D._angleToRandin, this._localRotation);
	            this._localQuaternionUpdate = false;
	        }
	        return this._localRotation;
	    }
	    set localRotation(value) {
	        this._localRotation = value;
	        this._locaEulerlUpdate = true;
	        this._localQuaternionUpdate = false;
	        this._localUpdate = true;
	        this._onWorldTransform();
	    }
	    get localScale() {
	        return this._localScale;
	    }
	    set localScale(value) {
	        this._localScale = value;
	        this._localUpdate = true;
	        this._onWorldTransform();
	    }
	    get localRotationEuler() {
	        if (this._locaEulerlUpdate) {
	            this._localRotation.getYawPitchRoll(AnimationTransform3D._tempVector3);
	            var euler = AnimationTransform3D._tempVector3;
	            var localRotationEuler = this._localRotationEuler;
	            localRotationEuler.x = euler.y * AnimationTransform3D._angleToRandin;
	            localRotationEuler.y = euler.x * AnimationTransform3D._angleToRandin;
	            localRotationEuler.z = euler.z * AnimationTransform3D._angleToRandin;
	            this._locaEulerlUpdate = false;
	        }
	        return this._localRotationEuler;
	    }
	    set localRotationEuler(value) {
	        this._localRotationEuler = value;
	        this._locaEulerlUpdate = false;
	        this._localQuaternionUpdate = true;
	        this._localUpdate = true;
	        this._onWorldTransform();
	    }
	    getWorldMatrix() {
	        if (!Laya.Render.supportWebGLPlusAnimation && this._worldUpdate) {
	            if (this._parent != null) {
	                Utils3D.matrix4x4MultiplyFFF(this._parent.getWorldMatrix(), this._getlocalMatrix(), this._worldMatrix);
	            }
	            else {
	                var e = this._worldMatrix;
	                e[1] = e[2] = e[3] = e[4] = e[6] = e[7] = e[8] = e[9] = e[11] = e[12] = e[13] = e[14] = 0;
	                e[0] = e[5] = e[10] = e[15] = 1;
	            }
	            this._worldUpdate = false;
	        }
	        if (Laya.Render.supportWebGLPlusAnimation && this._worldUpdate) {
	            this._worldUpdate = false;
	        }
	        return this._worldMatrix;
	    }
	    setParent(value) {
	        if (this._parent !== value) {
	            if (this._parent) {
	                var parentChilds = this._parent._children;
	                var index = parentChilds.indexOf(this);
	                parentChilds.splice(index, 1);
	            }
	            if (value) {
	                value._children.push(this);
	                (value) && (this._onWorldTransform());
	            }
	            this._parent = value;
	        }
	    }
	}
	AnimationTransform3D._tempVector3 = new Vector3();
	AnimationTransform3D._angleToRandin = 180 / Math.PI;

	class AnimationNode {
	    constructor(localPosition = null, localRotation = null, localScale = null, worldMatrix = null) {
	        this._children = [];
	        this.transform = new AnimationTransform3D(this, localPosition, localRotation, localScale, worldMatrix);
	    }
	    addChild(child) {
	        child._parent = this;
	        child.transform.setParent(this.transform);
	        this._children.push(child);
	    }
	    removeChild(child) {
	        var index = this._children.indexOf(child);
	        (index !== -1) && (this._children.splice(index, 1));
	    }
	    getChildByName(name) {
	        for (var i = 0, n = this._children.length; i < n; i++) {
	            var child = this._children[i];
	            if (child.name === name)
	                return child;
	        }
	        return null;
	    }
	    getChildByIndex(index) {
	        return this._children[index];
	    }
	    getChildCount() {
	        return this._children.length;
	    }
	    cloneTo(destObject) {
	        var destNode = destObject;
	        destNode.name = this.name;
	        for (var i = 0, n = this._children.length; i < n; i++) {
	            var child = this._children[i];
	            var destChild = child.clone();
	            destNode.addChild(destChild);
	            var transform = child.transform;
	            var destTransform = destChild.transform;
	            var destLocalPosition = destTransform.localPosition;
	            var destLocalRotation = destTransform.localRotation;
	            var destLocalScale = destTransform.localScale;
	            transform.localPosition.cloneTo(destLocalPosition);
	            transform.localRotation.cloneTo(destLocalRotation);
	            transform.localScale.cloneTo(destLocalScale);
	            destTransform.localPosition = destLocalPosition;
	            destTransform.localRotation = destLocalRotation;
	            destTransform.localScale = destLocalScale;
	        }
	    }
	    clone() {
	        var dest = new AnimationNode();
	        this.cloneTo(dest);
	        return dest;
	    }
	    _cloneNative(localPositions, localRotations, localScales, animationNodeWorldMatrixs, animationNodeParentIndices, parentIndex, avatar) {
	        var curID = avatar._nativeCurCloneCount;
	        animationNodeParentIndices[curID] = parentIndex;
	        var localPosition = new Float32Array(localPositions.buffer, curID * 3 * 4, 3);
	        var localRotation = new Float32Array(localRotations.buffer, curID * 4 * 4, 4);
	        var localScale = new Float32Array(localScales.buffer, curID * 3 * 4, 3);
	        var worldMatrix = new Float32Array(animationNodeWorldMatrixs.buffer, curID * 16 * 4, 16);
	        var dest = new AnimationNode(localPosition, localRotation, localScale, worldMatrix);
	        dest._worldMatrixIndex = curID;
	        this._cloneToNative(dest, localPositions, localRotations, localScales, animationNodeWorldMatrixs, animationNodeParentIndices, curID, avatar);
	        return dest;
	    }
	    _cloneToNative(destObject, localPositions, localRotations, localScales, animationNodeWorldMatrixs, animationNodeParentIndices, parentIndex, avatar) {
	        var destNode = destObject;
	        destNode.name = this.name;
	        for (var i = 0, n = this._children.length; i < n; i++) {
	            var child = this._children[i];
	            avatar._nativeCurCloneCount++;
	            var destChild = child._cloneNative(localPositions, localRotations, localScales, animationNodeWorldMatrixs, animationNodeParentIndices, parentIndex, avatar);
	            destNode.addChild(destChild);
	            var transform = child.transform;
	            var destTransform = destChild.transform;
	            var destLocalPosition = destTransform.localPosition;
	            var destLocalRotation = destTransform.localRotation;
	            var destLocalScale = destTransform.localScale;
	            transform.localPosition.cloneTo(destLocalPosition);
	            transform.localRotation.cloneTo(destLocalRotation);
	            transform.localScale.cloneTo(destLocalScale);
	            destTransform.localPosition = destLocalPosition;
	            destTransform.localRotation = destLocalRotation;
	            destTransform.localScale = destLocalScale;
	        }
	    }
	}

	class Avatar extends Laya.Resource {
	    constructor() {
	        super();
	        this._nativeNodeCount = 0;
	        this._nativeCurCloneCount = 0;
	    }
	    static _parse(data, propertyParams = null, constructParams = null) {
	        var avatar = new Avatar();
	        avatar._rootNode = new AnimationNode(new Float32Array(3), new Float32Array(4), new Float32Array(3), new Float32Array(16));
	        if (Laya.Render.supportWebGLPlusAnimation)
	            avatar._nativeNodeCount++;
	        if (data.version) {
	            var rootNode = data.rootNode;
	            (rootNode) && (avatar._parseNode(rootNode, avatar._rootNode));
	        }
	        return avatar;
	    }
	    static load(url, complete) {
	        Laya.ILaya.loader.create(url, complete, null, Avatar.AVATAR);
	    }
	    _initCloneToAnimator(destNode, destAnimator) {
	        destAnimator._avatarNodeMap[destNode.name] = destNode;
	        for (var i = 0, n = destNode.getChildCount(); i < n; i++)
	            this._initCloneToAnimator(destNode.getChildByIndex(i), destAnimator);
	    }
	    _parseNode(nodaData, node) {
	        var name = nodaData.props.name;
	        node.name = name;
	        var props = nodaData.props;
	        var transform = node.transform;
	        var pos = transform.localPosition;
	        var rot = transform.localRotation;
	        var sca = transform.localScale;
	        pos.fromArray(props.translate);
	        rot.fromArray(props.rotation);
	        sca.fromArray(props.scale);
	        transform.localPosition = pos;
	        transform.localRotation = rot;
	        transform.localScale = sca;
	        var childrenData = nodaData.child;
	        for (var j = 0, n = childrenData.length; j < n; j++) {
	            var childData = childrenData[j];
	            var childBone = new AnimationNode(new Float32Array(3), new Float32Array(4), new Float32Array(3), new Float32Array(16));
	            node.addChild(childBone);
	            if (Laya.Render.supportWebGLPlusAnimation)
	                this._nativeNodeCount++;
	            this._parseNode(childData, childBone);
	        }
	    }
	    _cloneDatasToAnimator(destAnimator) {
	        var destRoot;
	        destRoot = this._rootNode.clone();
	        var transform = this._rootNode.transform;
	        var destTransform = destRoot.transform;
	        var destPosition = destTransform.localPosition;
	        var destRotation = destTransform.localRotation;
	        var destScale = destTransform.localScale;
	        transform.localPosition.cloneTo(destPosition);
	        transform.localRotation.cloneTo(destRotation);
	        transform.localScale.cloneTo(destScale);
	        destTransform.localPosition = destPosition;
	        destTransform.localRotation = destRotation;
	        destTransform.localScale = destScale;
	        destAnimator._avatarNodeMap = {};
	        this._initCloneToAnimator(destRoot, destAnimator);
	    }
	    cloneTo(destObject) {
	        var destAvatar = destObject;
	        var destRoot = this._rootNode.clone();
	        destAvatar._rootNode = destRoot;
	    }
	    clone() {
	        var dest = new Avatar();
	        this.cloneTo(dest);
	        return dest;
	    }
	    _cloneDatasToAnimatorNative(destAnimator) {
	        var animationNodeLocalPositions = new Float32Array(this._nativeNodeCount * 3);
	        var animationNodeLocalRotations = new Float32Array(this._nativeNodeCount * 4);
	        var animationNodeLocalScales = new Float32Array(this._nativeNodeCount * 3);
	        var animationNodeWorldMatrixs = new Float32Array(this._nativeNodeCount * 16);
	        var animationNodeParentIndices = new Int16Array(this._nativeNodeCount);
	        destAnimator._animationNodeLocalPositions = animationNodeLocalPositions;
	        destAnimator._animationNodeLocalRotations = animationNodeLocalRotations;
	        destAnimator._animationNodeLocalScales = animationNodeLocalScales;
	        destAnimator._animationNodeWorldMatrixs = animationNodeWorldMatrixs;
	        destAnimator._animationNodeParentIndices = animationNodeParentIndices;
	        this._nativeCurCloneCount = 0;
	        var destRoot = this._rootNode._cloneNative(animationNodeLocalPositions, animationNodeLocalRotations, animationNodeLocalScales, animationNodeWorldMatrixs, animationNodeParentIndices, -1, this);
	        var transform = this._rootNode.transform;
	        var destTransform = destRoot.transform;
	        var destPosition = destTransform.localPosition;
	        var destRotation = destTransform.localRotation;
	        var destScale = destTransform.localScale;
	        transform.localPosition.cloneTo(destPosition);
	        transform.localRotation.cloneTo(destRotation);
	        transform.localScale.cloneTo(destScale);
	        destTransform.localPosition = destPosition;
	        destTransform.localRotation = destRotation;
	        destTransform.localScale = destScale;
	        destAnimator._avatarNodeMap = {};
	        this._initCloneToAnimator(destRoot, destAnimator);
	    }
	}
	Avatar.AVATAR = "AVATAR";

	class BaseMaterial extends Laya.Resource {
	    constructor() {
	        super();
	        this._shaderValues = null;
	        this._disablePublicDefineDatas = new DefineDatas();
	        this._shaderValues = new ShaderData(this);
	        this.renderQueue = BaseMaterial.RENDERQUEUE_OPAQUE;
	        this._alphaTest = false;
	    }
	    static load(url, complete) {
	        Laya.Laya.loader.create(url, complete, null, BaseMaterial.MATERIAL);
	    }
	    static __initDefine__() {
	        BaseMaterial.SHADERDEFINE_ALPHATEST = Shader3D.getDefineByName("ALPHATEST");
	    }
	    static _parse(data, propertyParams = null, constructParams = null) {
	        var jsonData = data;
	        var props = jsonData.props;
	        var material;
	        var classType = props.type;
	        var clas = Laya.ClassUtils.getRegClass(classType);
	        if (clas)
	            material = new clas();
	        else
	            throw ('_getSprite3DHierarchyInnerUrls 错误: ' + data.type + ' 不是类');
	        switch (jsonData.version) {
	            case "LAYAMATERIAL:01":
	            case "LAYAMATERIAL:02":
	                var i, n;
	                for (var key in props) {
	                    switch (key) {
	                        case "vectors":
	                            var vectors = props[key];
	                            for (i = 0, n = vectors.length; i < n; i++) {
	                                var vector = vectors[i];
	                                var vectorValue = vector.value;
	                                switch (vectorValue.length) {
	                                    case 2:
	                                        material[vector.name] = new Vector2(vectorValue[0], vectorValue[1]);
	                                        break;
	                                    case 3:
	                                        material[vector.name] = new Vector3(vectorValue[0], vectorValue[1], vectorValue[2]);
	                                        break;
	                                    case 4:
	                                        material[vector.name] = new Vector4(vectorValue[0], vectorValue[1], vectorValue[2], vectorValue[3]);
	                                        break;
	                                    default:
	                                        throw new Error("BaseMaterial:unkonwn color length.");
	                                }
	                            }
	                            break;
	                        case "textures":
	                            var textures = props[key];
	                            for (i = 0, n = textures.length; i < n; i++) {
	                                var texture = textures[i];
	                                var path = texture.path;
	                                (path) && (material[texture.name] = Laya.Loader.getRes(path));
	                            }
	                            break;
	                        case "defines":
	                            var defineNames = props[key];
	                            for (i = 0, n = defineNames.length; i < n; i++) {
	                                var define = Shader3D.getDefineByName(defineNames[i]);
	                                material._shaderValues.addDefine(define);
	                            }
	                            break;
	                        case "renderStates":
	                            var renderStatesData = props[key];
	                            var renderStateData = renderStatesData[0];
	                            var mat = material;
	                            mat.blend = renderStateData.blend;
	                            mat.cull = renderStateData.cull;
	                            mat.depthTest = renderStateData.depthTest;
	                            mat.depthWrite = renderStateData.depthWrite;
	                            mat.blendSrc = renderStateData.srcBlend;
	                            mat.blendDst = renderStateData.dstBlend;
	                            break;
	                        case "cull":
	                            material.cull = props[key];
	                            break;
	                        case "blend":
	                            material.blend = props[key];
	                            break;
	                        case "depthWrite":
	                            material.depthWrite = props[key];
	                            break;
	                        case "srcBlend":
	                            material.blendSrc = props[key];
	                            break;
	                        case "dstBlend":
	                            material.blendDst = props[key];
	                            break;
	                        default:
	                            material[key] = props[key];
	                    }
	                }
	                break;
	            default:
	                throw new Error("BaseMaterial:unkonwn version.");
	        }
	        return material;
	    }
	    get alphaTestValue() {
	        return this._shaderValues.getNumber(BaseMaterial.ALPHATESTVALUE);
	    }
	    set alphaTestValue(value) {
	        this._shaderValues.setNumber(BaseMaterial.ALPHATESTVALUE, value);
	    }
	    get alphaTest() {
	        return this._alphaTest;
	    }
	    set alphaTest(value) {
	        this._alphaTest = value;
	        if (value)
	            this._shaderValues.addDefine(BaseMaterial.SHADERDEFINE_ALPHATEST);
	        else
	            this._shaderValues.removeDefine(BaseMaterial.SHADERDEFINE_ALPHATEST);
	    }
	    _removeTetxureReference() {
	        var data = this._shaderValues.getData();
	        for (var k in data) {
	            var value = data[k];
	            if (value && value instanceof Laya.BaseTexture)
	                value._removeReference();
	        }
	    }
	    _addReference(count = 1) {
	        super._addReference(count);
	        var data = this._shaderValues.getData();
	        for (var k in data) {
	            var value = data[k];
	            if (value && value instanceof Laya.BaseTexture)
	                value._addReference();
	        }
	    }
	    _removeReference(count = 1) {
	        super._removeReference(count);
	        this._removeTetxureReference();
	    }
	    _disposeResource() {
	        if (this._referenceCount > 0)
	            this._removeTetxureReference();
	        this._shaderValues = null;
	    }
	    setShaderName(name) {
	        this._shader = Shader3D.find(name);
	        if (!this._shader)
	            throw new Error("BaseMaterial: unknown shader name.");
	    }
	    cloneTo(destObject) {
	        var destBaseMaterial = destObject;
	        destBaseMaterial.name = this.name;
	        destBaseMaterial.renderQueue = this.renderQueue;
	        this._disablePublicDefineDatas.cloneTo(destBaseMaterial._disablePublicDefineDatas);
	        this._shaderValues.cloneTo(destBaseMaterial._shaderValues);
	    }
	    clone() {
	        var dest = new BaseMaterial();
	        this.cloneTo(dest);
	        return dest;
	    }
	    get _defineDatas() {
	        return this._shaderValues._defineDatas;
	    }
	}
	BaseMaterial.MATERIAL = "MATERIAL";
	BaseMaterial.RENDERQUEUE_OPAQUE = 2000;
	BaseMaterial.RENDERQUEUE_ALPHATEST = 2450;
	BaseMaterial.RENDERQUEUE_TRANSPARENT = 3000;
	BaseMaterial.ALPHATESTVALUE = Shader3D.propertyNameToID("u_AlphaTestValue");
	BaseMaterial.SHADERDEFINE_ALPHATEST = null;

	class Scene3DShaderDeclaration {
	}

	class RenderState {
	    constructor() {
	        this.cull = RenderState.CULL_BACK;
	        this.blend = RenderState.BLEND_DISABLE;
	        this.srcBlend = RenderState.BLENDPARAM_ONE;
	        this.dstBlend = RenderState.BLENDPARAM_ZERO;
	        this.srcBlendRGB = RenderState.BLENDPARAM_ONE;
	        this.dstBlendRGB = RenderState.BLENDPARAM_ZERO;
	        this.srcBlendAlpha = RenderState.BLENDPARAM_ONE;
	        this.dstBlendAlpha = RenderState.BLENDPARAM_ZERO;
	        this.blendConstColor = new Vector4(1, 1, 1, 1);
	        this.blendEquation = RenderState.BLENDEQUATION_ADD;
	        this.blendEquationRGB = RenderState.BLENDEQUATION_ADD;
	        this.blendEquationAlpha = RenderState.BLENDEQUATION_ADD;
	        this.depthTest = RenderState.DEPTHTEST_LEQUAL;
	        this.depthWrite = true;
	    }
	    cloneTo(dest) {
	        var destState = dest;
	        destState.cull = this.cull;
	        destState.blend = this.blend;
	        destState.srcBlend = this.srcBlend;
	        destState.dstBlend = this.dstBlend;
	        destState.srcBlendRGB = this.srcBlendRGB;
	        destState.dstBlendRGB = this.dstBlendRGB;
	        destState.srcBlendAlpha = this.srcBlendAlpha;
	        destState.dstBlendAlpha = this.dstBlendAlpha;
	        this.blendConstColor.cloneTo(destState.blendConstColor);
	        destState.blendEquation = this.blendEquation;
	        destState.blendEquationRGB = this.blendEquationRGB;
	        destState.blendEquationAlpha = this.blendEquationAlpha;
	        destState.depthTest = this.depthTest;
	        destState.depthWrite = this.depthWrite;
	    }
	    clone() {
	        var dest = new RenderState();
	        this.cloneTo(dest);
	        return dest;
	    }
	}
	RenderState.CULL_NONE = 0;
	RenderState.CULL_FRONT = 1;
	RenderState.CULL_BACK = 2;
	RenderState.BLEND_DISABLE = 0;
	RenderState.BLEND_ENABLE_ALL = 1;
	RenderState.BLEND_ENABLE_SEPERATE = 2;
	RenderState.BLENDPARAM_ZERO = 0;
	RenderState.BLENDPARAM_ONE = 1;
	RenderState.BLENDPARAM_SRC_COLOR = 0x0300;
	RenderState.BLENDPARAM_ONE_MINUS_SRC_COLOR = 0x0301;
	RenderState.BLENDPARAM_DST_COLOR = 0x0306;
	RenderState.BLENDPARAM_ONE_MINUS_DST_COLOR = 0x0307;
	RenderState.BLENDPARAM_SRC_ALPHA = 0x0302;
	RenderState.BLENDPARAM_ONE_MINUS_SRC_ALPHA = 0x0303;
	RenderState.BLENDPARAM_DST_ALPHA = 0x0304;
	RenderState.BLENDPARAM_ONE_MINUS_DST_ALPHA = 0x0305;
	RenderState.BLENDPARAM_SRC_ALPHA_SATURATE = 0x0308;
	RenderState.BLENDEQUATION_ADD = 0x8006;
	RenderState.BLENDEQUATION_SUBTRACT = 0x800A;
	RenderState.BLENDEQUATION_REVERSE_SUBTRACT = 0x800B;
	RenderState.DEPTHTEST_OFF = 0;
	RenderState.DEPTHTEST_NEVER = 0x0200;
	RenderState.DEPTHTEST_LESS = 0x0201;
	RenderState.DEPTHTEST_EQUAL = 0x0202;
	RenderState.DEPTHTEST_LEQUAL = 0x0203;
	RenderState.DEPTHTEST_GREATER = 0x0204;
	RenderState.DEPTHTEST_NOTEQUAL = 0x0205;
	RenderState.DEPTHTEST_GEQUAL = 0x0206;
	RenderState.DEPTHTEST_ALWAYS = 0x0207;

	class BlinnPhongMaterial extends BaseMaterial {
	    constructor() {
	        super();
	        this._enableVertexColor = false;
	        this.setShaderName("BLINNPHONG");
	        this._albedoIntensity = 1.0;
	        this._albedoColor = new Vector4(1.0, 1.0, 1.0, 1.0);
	        var sv = this._shaderValues;
	        sv.setVector(BlinnPhongMaterial.ALBEDOCOLOR, new Vector4(1.0, 1.0, 1.0, 1.0));
	        sv.setVector(BlinnPhongMaterial.MATERIALSPECULAR, new Vector4(1.0, 1.0, 1.0, 1.0));
	        sv.setNumber(BlinnPhongMaterial.SHININESS, 0.078125);
	        sv.setNumber(BaseMaterial.ALPHATESTVALUE, 0.5);
	        sv.setVector(BlinnPhongMaterial.TILINGOFFSET, new Vector4(1.0, 1.0, 0.0, 0.0));
	        this._enableLighting = true;
	        this.renderMode = BlinnPhongMaterial.RENDERMODE_OPAQUE;
	    }
	    static __initDefine__() {
	        BlinnPhongMaterial.SHADERDEFINE_DIFFUSEMAP = Shader3D.getDefineByName("DIFFUSEMAP");
	        BlinnPhongMaterial.SHADERDEFINE_NORMALMAP = Shader3D.getDefineByName("NORMALMAP");
	        BlinnPhongMaterial.SHADERDEFINE_SPECULARMAP = Shader3D.getDefineByName("SPECULARMAP");
	        BlinnPhongMaterial.SHADERDEFINE_TILINGOFFSET = Shader3D.getDefineByName("TILINGOFFSET");
	        BlinnPhongMaterial.SHADERDEFINE_ENABLEVERTEXCOLOR = Shader3D.getDefineByName("ENABLEVERTEXCOLOR");
	    }
	    get _ColorR() {
	        return this._albedoColor.x;
	    }
	    set _ColorR(value) {
	        this._albedoColor.x = value;
	        this.albedoColor = this._albedoColor;
	    }
	    get _ColorG() {
	        return this._albedoColor.y;
	    }
	    set _ColorG(value) {
	        this._albedoColor.y = value;
	        this.albedoColor = this._albedoColor;
	    }
	    get _ColorB() {
	        return this._albedoColor.z;
	    }
	    set _ColorB(value) {
	        this._albedoColor.z = value;
	        this.albedoColor = this._albedoColor;
	    }
	    get _ColorA() {
	        return this._albedoColor.w;
	    }
	    set _ColorA(value) {
	        this._albedoColor.w = value;
	        this.albedoColor = this._albedoColor;
	    }
	    get _SpecColorR() {
	        return this._shaderValues.getVector(BlinnPhongMaterial.MATERIALSPECULAR).x;
	    }
	    set _SpecColorR(value) {
	        this._shaderValues.getVector(BlinnPhongMaterial.MATERIALSPECULAR).x = value;
	    }
	    get _SpecColorG() {
	        return this._shaderValues.getVector(BlinnPhongMaterial.MATERIALSPECULAR).y;
	    }
	    set _SpecColorG(value) {
	        this._shaderValues.getVector(BlinnPhongMaterial.MATERIALSPECULAR).y = value;
	    }
	    get _SpecColorB() {
	        return this._shaderValues.getVector(BlinnPhongMaterial.MATERIALSPECULAR).z;
	    }
	    set _SpecColorB(value) {
	        this._shaderValues.getVector(BlinnPhongMaterial.MATERIALSPECULAR).z = value;
	    }
	    get _SpecColorA() {
	        return this._shaderValues.getVector(BlinnPhongMaterial.MATERIALSPECULAR).w;
	    }
	    set _SpecColorA(value) {
	        this._shaderValues.getVector(BlinnPhongMaterial.MATERIALSPECULAR).w = value;
	    }
	    get _AlbedoIntensity() {
	        return this._albedoIntensity;
	    }
	    set _AlbedoIntensity(value) {
	        if (this._albedoIntensity !== value) {
	            var finalAlbedo = this._shaderValues.getVector(BlinnPhongMaterial.ALBEDOCOLOR);
	            Vector4.scale(this._albedoColor, value, finalAlbedo);
	            this._albedoIntensity = value;
	            this._shaderValues.setVector(BlinnPhongMaterial.ALBEDOCOLOR, finalAlbedo);
	        }
	    }
	    get _Shininess() {
	        return this._shaderValues.getNumber(BlinnPhongMaterial.SHININESS);
	    }
	    set _Shininess(value) {
	        value = Math.max(0.0, Math.min(1.0, value));
	        this._shaderValues.setNumber(BlinnPhongMaterial.SHININESS, value);
	    }
	    get _MainTex_STX() {
	        return this._shaderValues.getVector(BlinnPhongMaterial.TILINGOFFSET).x;
	    }
	    set _MainTex_STX(x) {
	        var tilOff = this._shaderValues.getVector(BlinnPhongMaterial.TILINGOFFSET);
	        tilOff.x = x;
	        this.tilingOffset = tilOff;
	    }
	    get _MainTex_STY() {
	        return this._shaderValues.getVector(BlinnPhongMaterial.TILINGOFFSET).y;
	    }
	    set _MainTex_STY(y) {
	        var tilOff = this._shaderValues.getVector(BlinnPhongMaterial.TILINGOFFSET);
	        tilOff.y = y;
	        this.tilingOffset = tilOff;
	    }
	    get _MainTex_STZ() {
	        return this._shaderValues.getVector(BlinnPhongMaterial.TILINGOFFSET).z;
	    }
	    set _MainTex_STZ(z) {
	        var tilOff = this._shaderValues.getVector(BlinnPhongMaterial.TILINGOFFSET);
	        tilOff.z = z;
	        this.tilingOffset = tilOff;
	    }
	    get _MainTex_STW() {
	        return this._shaderValues.getVector(BlinnPhongMaterial.TILINGOFFSET).w;
	    }
	    set _MainTex_STW(w) {
	        var tilOff = this._shaderValues.getVector(BlinnPhongMaterial.TILINGOFFSET);
	        tilOff.w = w;
	        this.tilingOffset = tilOff;
	    }
	    get _Cutoff() {
	        return this.alphaTestValue;
	    }
	    set _Cutoff(value) {
	        this.alphaTestValue = value;
	    }
	    set renderMode(value) {
	        switch (value) {
	            case BlinnPhongMaterial.RENDERMODE_OPAQUE:
	                this.alphaTest = false;
	                this.renderQueue = BaseMaterial.RENDERQUEUE_OPAQUE;
	                this.depthWrite = true;
	                this.cull = RenderState.CULL_BACK;
	                this.blend = RenderState.BLEND_DISABLE;
	                this.depthTest = RenderState.DEPTHTEST_LESS;
	                break;
	            case BlinnPhongMaterial.RENDERMODE_CUTOUT:
	                this.renderQueue = BaseMaterial.RENDERQUEUE_ALPHATEST;
	                this.alphaTest = true;
	                this.depthWrite = true;
	                this.cull = RenderState.CULL_BACK;
	                this.blend = RenderState.BLEND_DISABLE;
	                this.depthTest = RenderState.DEPTHTEST_LESS;
	                break;
	            case BlinnPhongMaterial.RENDERMODE_TRANSPARENT:
	                this.renderQueue = BaseMaterial.RENDERQUEUE_TRANSPARENT;
	                this.alphaTest = false;
	                this.depthWrite = false;
	                this.cull = RenderState.CULL_BACK;
	                this.blend = RenderState.BLEND_ENABLE_ALL;
	                this.blendSrc = RenderState.BLENDPARAM_SRC_ALPHA;
	                this.blendDst = RenderState.BLENDPARAM_ONE_MINUS_SRC_ALPHA;
	                this.depthTest = RenderState.DEPTHTEST_LESS;
	                break;
	            default:
	                throw new Error("Material:renderMode value error.");
	        }
	    }
	    get enableVertexColor() {
	        return this._enableVertexColor;
	    }
	    set enableVertexColor(value) {
	        this._enableVertexColor = value;
	        if (value)
	            this._shaderValues.addDefine(BlinnPhongMaterial.SHADERDEFINE_ENABLEVERTEXCOLOR);
	        else
	            this._shaderValues.removeDefine(BlinnPhongMaterial.SHADERDEFINE_ENABLEVERTEXCOLOR);
	    }
	    get tilingOffsetX() {
	        return this._MainTex_STX;
	    }
	    set tilingOffsetX(x) {
	        this._MainTex_STX = x;
	    }
	    get tilingOffsetY() {
	        return this._MainTex_STY;
	    }
	    set tilingOffsetY(y) {
	        this._MainTex_STY = y;
	    }
	    get tilingOffsetZ() {
	        return this._MainTex_STZ;
	    }
	    set tilingOffsetZ(z) {
	        this._MainTex_STZ = z;
	    }
	    get tilingOffsetW() {
	        return this._MainTex_STW;
	    }
	    set tilingOffsetW(w) {
	        this._MainTex_STW = w;
	    }
	    get tilingOffset() {
	        return this._shaderValues.getVector(BlinnPhongMaterial.TILINGOFFSET);
	    }
	    set tilingOffset(value) {
	        if (value) {
	            if (value.x != 1 || value.y != 1 || value.z != 0 || value.w != 0)
	                this._shaderValues.addDefine(BlinnPhongMaterial.SHADERDEFINE_TILINGOFFSET);
	            else
	                this._shaderValues.removeDefine(BlinnPhongMaterial.SHADERDEFINE_TILINGOFFSET);
	        }
	        else {
	            this._shaderValues.removeDefine(BlinnPhongMaterial.SHADERDEFINE_TILINGOFFSET);
	        }
	        this._shaderValues.setVector(BlinnPhongMaterial.TILINGOFFSET, value);
	    }
	    get albedoColorR() {
	        return this._ColorR;
	    }
	    set albedoColorR(value) {
	        this._ColorR = value;
	    }
	    get albedoColorG() {
	        return this._ColorG;
	    }
	    set albedoColorG(value) {
	        this._ColorG = value;
	    }
	    get albedoColorB() {
	        return this._ColorB;
	    }
	    set albedoColorB(value) {
	        this._ColorB = value;
	    }
	    get albedoColorA() {
	        return this._ColorA;
	    }
	    set albedoColorA(value) {
	        this._ColorA = value;
	    }
	    get albedoColor() {
	        return this._albedoColor;
	    }
	    set albedoColor(value) {
	        var finalAlbedo = this._shaderValues.getVector(BlinnPhongMaterial.ALBEDOCOLOR);
	        Vector4.scale(value, this._albedoIntensity, finalAlbedo);
	        this._albedoColor = value;
	        this._shaderValues.setVector(BlinnPhongMaterial.ALBEDOCOLOR, finalAlbedo);
	    }
	    get albedoIntensity() {
	        return this._albedoIntensity;
	    }
	    set albedoIntensity(value) {
	        this._AlbedoIntensity = value;
	    }
	    get specularColorR() {
	        return this._SpecColorR;
	    }
	    set specularColorR(value) {
	        this._SpecColorR = value;
	    }
	    get specularColorG() {
	        return this._SpecColorG;
	    }
	    set specularColorG(value) {
	        this._SpecColorG = value;
	    }
	    get specularColorB() {
	        return this._SpecColorB;
	    }
	    set specularColorB(value) {
	        this._SpecColorB = value;
	    }
	    get specularColorA() {
	        return this._SpecColorA;
	    }
	    set specularColorA(value) {
	        this._SpecColorA = value;
	    }
	    get specularColor() {
	        return this._shaderValues.getVector(BlinnPhongMaterial.MATERIALSPECULAR);
	    }
	    set specularColor(value) {
	        this._shaderValues.setVector(BlinnPhongMaterial.MATERIALSPECULAR, value);
	    }
	    get shininess() {
	        return this._Shininess;
	    }
	    set shininess(value) {
	        this._Shininess = value;
	    }
	    get albedoTexture() {
	        return this._shaderValues.getTexture(BlinnPhongMaterial.ALBEDOTEXTURE);
	    }
	    set albedoTexture(value) {
	        if (value)
	            this._shaderValues.addDefine(BlinnPhongMaterial.SHADERDEFINE_DIFFUSEMAP);
	        else
	            this._shaderValues.removeDefine(BlinnPhongMaterial.SHADERDEFINE_DIFFUSEMAP);
	        this._shaderValues.setTexture(BlinnPhongMaterial.ALBEDOTEXTURE, value);
	    }
	    get normalTexture() {
	        return this._shaderValues.getTexture(BlinnPhongMaterial.NORMALTEXTURE);
	    }
	    set normalTexture(value) {
	        if (value)
	            this._shaderValues.addDefine(BlinnPhongMaterial.SHADERDEFINE_NORMALMAP);
	        else
	            this._shaderValues.removeDefine(BlinnPhongMaterial.SHADERDEFINE_NORMALMAP);
	        this._shaderValues.setTexture(BlinnPhongMaterial.NORMALTEXTURE, value);
	    }
	    get specularTexture() {
	        return this._shaderValues.getTexture(BlinnPhongMaterial.SPECULARTEXTURE);
	    }
	    set specularTexture(value) {
	        if (value)
	            this._shaderValues.addDefine(BlinnPhongMaterial.SHADERDEFINE_SPECULARMAP);
	        else
	            this._shaderValues.removeDefine(BlinnPhongMaterial.SHADERDEFINE_SPECULARMAP);
	        this._shaderValues.setTexture(BlinnPhongMaterial.SPECULARTEXTURE, value);
	    }
	    get enableLighting() {
	        return this._enableLighting;
	    }
	    set enableLighting(value) {
	        if (this._enableLighting !== value) {
	            if (value) {
	                this._disablePublicDefineDatas.remove(Scene3DShaderDeclaration.SHADERDEFINE_POINTLIGHT);
	                this._disablePublicDefineDatas.remove(Scene3DShaderDeclaration.SHADERDEFINE_SPOTLIGHT);
	                this._disablePublicDefineDatas.remove(Scene3DShaderDeclaration.SHADERDEFINE_DIRECTIONLIGHT);
	            }
	            else {
	                this._disablePublicDefineDatas.add(Scene3DShaderDeclaration.SHADERDEFINE_POINTLIGHT);
	                this._disablePublicDefineDatas.add(Scene3DShaderDeclaration.SHADERDEFINE_SPOTLIGHT);
	                this._disablePublicDefineDatas.add(Scene3DShaderDeclaration.SHADERDEFINE_DIRECTIONLIGHT);
	            }
	            this._enableLighting = value;
	        }
	    }
	    get depthWrite() {
	        return this._shaderValues.getBool(BlinnPhongMaterial.DEPTH_WRITE);
	    }
	    set depthWrite(value) {
	        this._shaderValues.setBool(BlinnPhongMaterial.DEPTH_WRITE, value);
	    }
	    get cull() {
	        return this._shaderValues.getInt(BlinnPhongMaterial.CULL);
	    }
	    set cull(value) {
	        this._shaderValues.setInt(BlinnPhongMaterial.CULL, value);
	    }
	    get blend() {
	        return this._shaderValues.getInt(BlinnPhongMaterial.BLEND);
	    }
	    set blend(value) {
	        this._shaderValues.setInt(BlinnPhongMaterial.BLEND, value);
	    }
	    get blendSrc() {
	        return this._shaderValues.getInt(BlinnPhongMaterial.BLEND_SRC);
	    }
	    set blendSrc(value) {
	        this._shaderValues.setInt(BlinnPhongMaterial.BLEND_SRC, value);
	    }
	    get blendDst() {
	        return this._shaderValues.getInt(BlinnPhongMaterial.BLEND_DST);
	    }
	    set blendDst(value) {
	        this._shaderValues.setInt(BlinnPhongMaterial.BLEND_DST, value);
	    }
	    get depthTest() {
	        return this._shaderValues.getInt(BlinnPhongMaterial.DEPTH_TEST);
	    }
	    set depthTest(value) {
	        this._shaderValues.setInt(BlinnPhongMaterial.DEPTH_TEST, value);
	    }
	    clone() {
	        var dest = new BlinnPhongMaterial();
	        this.cloneTo(dest);
	        return dest;
	    }
	    cloneTo(destObject) {
	        super.cloneTo(destObject);
	        var destMaterial = destObject;
	        destMaterial._enableLighting = this._enableLighting;
	        destMaterial._albedoIntensity = this._albedoIntensity;
	        destMaterial._enableVertexColor = this._enableVertexColor;
	        this._albedoColor.cloneTo(destMaterial._albedoColor);
	    }
	}
	BlinnPhongMaterial.RENDERMODE_OPAQUE = 0;
	BlinnPhongMaterial.RENDERMODE_CUTOUT = 1;
	BlinnPhongMaterial.RENDERMODE_TRANSPARENT = 2;
	BlinnPhongMaterial.ALBEDOTEXTURE = Shader3D.propertyNameToID("u_DiffuseTexture");
	BlinnPhongMaterial.NORMALTEXTURE = Shader3D.propertyNameToID("u_NormalTexture");
	BlinnPhongMaterial.SPECULARTEXTURE = Shader3D.propertyNameToID("u_SpecularTexture");
	BlinnPhongMaterial.ALBEDOCOLOR = Shader3D.propertyNameToID("u_DiffuseColor");
	BlinnPhongMaterial.MATERIALSPECULAR = Shader3D.propertyNameToID("u_MaterialSpecular");
	BlinnPhongMaterial.SHININESS = Shader3D.propertyNameToID("u_Shininess");
	BlinnPhongMaterial.TILINGOFFSET = Shader3D.propertyNameToID("u_TilingOffset");
	BlinnPhongMaterial.CULL = Shader3D.propertyNameToID("s_Cull");
	BlinnPhongMaterial.BLEND = Shader3D.propertyNameToID("s_Blend");
	BlinnPhongMaterial.BLEND_SRC = Shader3D.propertyNameToID("s_BlendSrc");
	BlinnPhongMaterial.BLEND_DST = Shader3D.propertyNameToID("s_BlendDst");
	BlinnPhongMaterial.DEPTH_TEST = Shader3D.propertyNameToID("s_DepthTest");
	BlinnPhongMaterial.DEPTH_WRITE = Shader3D.propertyNameToID("s_DepthWrite");

	class EffectMaterial extends BaseMaterial {
	    constructor() {
	        super();
	        this.setShaderName("Effect");
	        this._color = new Vector4(1.0, 1.0, 1.0, 1.0);
	        this._shaderValues.setVector(EffectMaterial.TINTCOLOR, new Vector4(1.0, 1.0, 1.0, 1.0));
	        this.renderMode = EffectMaterial.RENDERMODE_ADDTIVE;
	    }
	    static __initDefine__() {
	        EffectMaterial.SHADERDEFINE_MAINTEXTURE = Shader3D.getDefineByName("MAINTEXTURE");
	        EffectMaterial.SHADERDEFINE_TILINGOFFSET = Shader3D.getDefineByName("TILINGOFFSET");
	        EffectMaterial.SHADERDEFINE_ADDTIVEFOG = Shader3D.getDefineByName("ADDTIVEFOG");
	    }
	    get _TintColorR() {
	        return this._color.x;
	    }
	    set _TintColorR(value) {
	        this._color.x = value;
	        this.color = this._color;
	    }
	    get _TintColorG() {
	        return this._color.y;
	    }
	    set _TintColorG(value) {
	        this._color.y = value;
	        this.color = this._color;
	    }
	    get _TintColorB() {
	        return this._color.z;
	    }
	    set _TintColorB(value) {
	        this._color.z = value;
	        this.color = this._color;
	    }
	    get _TintColorA() {
	        return this._color.w;
	    }
	    set _TintColorA(value) {
	        this._color.w = value;
	        this.color = this._color;
	    }
	    get _MainTex_STX() {
	        return this._shaderValues.getVector(EffectMaterial.TILINGOFFSET).x;
	    }
	    set _MainTex_STX(x) {
	        var tilOff = this._shaderValues.getVector(EffectMaterial.TILINGOFFSET);
	        tilOff.x = x;
	        this.tilingOffset = tilOff;
	    }
	    get _MainTex_STY() {
	        return this._shaderValues.getVector(EffectMaterial.TILINGOFFSET).y;
	    }
	    set _MainTex_STY(y) {
	        var tilOff = this._shaderValues.getVector(EffectMaterial.TILINGOFFSET);
	        tilOff.y = y;
	        this.tilingOffset = tilOff;
	    }
	    get _MainTex_STZ() {
	        return this._shaderValues.getVector(EffectMaterial.TILINGOFFSET).z;
	    }
	    set _MainTex_STZ(z) {
	        var tilOff = this._shaderValues.getVector(EffectMaterial.TILINGOFFSET);
	        tilOff.z = z;
	        this.tilingOffset = tilOff;
	    }
	    get _MainTex_STW() {
	        return this._shaderValues.getVector(EffectMaterial.TILINGOFFSET).w;
	    }
	    set _MainTex_STW(w) {
	        var tilOff = this._shaderValues.getVector(EffectMaterial.TILINGOFFSET);
	        tilOff.w = w;
	        this.tilingOffset = tilOff;
	    }
	    set renderMode(value) {
	        switch (value) {
	            case EffectMaterial.RENDERMODE_ADDTIVE:
	                this.renderQueue = BaseMaterial.RENDERQUEUE_TRANSPARENT;
	                this.alphaTest = false;
	                this.depthWrite = false;
	                this.cull = RenderState.CULL_NONE;
	                this.blend = RenderState.BLEND_ENABLE_ALL;
	                this.blendSrc = RenderState.BLENDPARAM_SRC_ALPHA;
	                this.blendDst = RenderState.BLENDPARAM_ONE;
	                this.depthTest = RenderState.DEPTHTEST_LESS;
	                this._shaderValues.addDefine(EffectMaterial.SHADERDEFINE_ADDTIVEFOG);
	                break;
	            case EffectMaterial.RENDERMODE_ALPHABLENDED:
	                this.renderQueue = BaseMaterial.RENDERQUEUE_TRANSPARENT;
	                this.alphaTest = false;
	                this.depthWrite = false;
	                this.cull = RenderState.CULL_NONE;
	                this.blend = RenderState.BLEND_ENABLE_ALL;
	                this.blendSrc = RenderState.BLENDPARAM_SRC_ALPHA;
	                this.blendDst = RenderState.BLENDPARAM_ONE_MINUS_SRC_ALPHA;
	                this.depthTest = RenderState.DEPTHTEST_LESS;
	                this._shaderValues.removeDefine(EffectMaterial.SHADERDEFINE_ADDTIVEFOG);
	                break;
	            default:
	                throw new Error("MeshEffectMaterial : renderMode value error.");
	        }
	    }
	    get colorR() {
	        return this._TintColorR;
	    }
	    set colorR(value) {
	        this._TintColorR = value;
	    }
	    get colorG() {
	        return this._TintColorG;
	    }
	    set colorG(value) {
	        this._TintColorG = value;
	    }
	    get colorB() {
	        return this._TintColorB;
	    }
	    set colorB(value) {
	        this._TintColorB = value;
	    }
	    get colorA() {
	        return this._TintColorA;
	    }
	    set colorA(value) {
	        this._TintColorA = value;
	    }
	    get color() {
	        return this._shaderValues.getVector(EffectMaterial.TINTCOLOR);
	    }
	    set color(value) {
	        this._shaderValues.setVector(EffectMaterial.TINTCOLOR, value);
	    }
	    get texture() {
	        return this._shaderValues.getTexture(EffectMaterial.MAINTEXTURE);
	    }
	    set texture(value) {
	        if (value)
	            this._shaderValues.addDefine(EffectMaterial.SHADERDEFINE_MAINTEXTURE);
	        else
	            this._shaderValues.removeDefine(EffectMaterial.SHADERDEFINE_MAINTEXTURE);
	        this._shaderValues.setTexture(EffectMaterial.MAINTEXTURE, value);
	    }
	    get tilingOffsetX() {
	        return this._MainTex_STX;
	    }
	    set tilingOffsetX(x) {
	        this._MainTex_STX = x;
	    }
	    get tilingOffsetY() {
	        return this._MainTex_STY;
	    }
	    set tilingOffsetY(y) {
	        this._MainTex_STY = y;
	    }
	    get tilingOffsetZ() {
	        return this._MainTex_STZ;
	    }
	    set tilingOffsetZ(z) {
	        this._MainTex_STZ = z;
	    }
	    get tilingOffsetW() {
	        return this._MainTex_STW;
	    }
	    set tilingOffsetW(w) {
	        this._MainTex_STW = w;
	    }
	    get tilingOffset() {
	        return this._shaderValues.getVector(EffectMaterial.TILINGOFFSET);
	    }
	    set tilingOffset(value) {
	        if (value) {
	            if (value.x != 1 || value.y != 1 || value.z != 0 || value.w != 0)
	                this._shaderValues.addDefine(EffectMaterial.SHADERDEFINE_TILINGOFFSET);
	            else
	                this._shaderValues.removeDefine(EffectMaterial.SHADERDEFINE_TILINGOFFSET);
	        }
	        else {
	            this._shaderValues.removeDefine(EffectMaterial.SHADERDEFINE_TILINGOFFSET);
	        }
	        this._shaderValues.setVector(EffectMaterial.TILINGOFFSET, value);
	    }
	    set depthWrite(value) {
	        this._shaderValues.setBool(EffectMaterial.DEPTH_WRITE, value);
	    }
	    get depthWrite() {
	        return this._shaderValues.getBool(EffectMaterial.DEPTH_WRITE);
	    }
	    set cull(value) {
	        this._shaderValues.setInt(EffectMaterial.CULL, value);
	    }
	    get cull() {
	        return this._shaderValues.getInt(EffectMaterial.CULL);
	    }
	    set blend(value) {
	        this._shaderValues.setInt(EffectMaterial.BLEND, value);
	    }
	    get blend() {
	        return this._shaderValues.getInt(EffectMaterial.BLEND);
	    }
	    set blendSrc(value) {
	        this._shaderValues.setInt(EffectMaterial.BLEND_SRC, value);
	    }
	    get blendSrc() {
	        return this._shaderValues.getInt(EffectMaterial.BLEND_SRC);
	    }
	    set blendDst(value) {
	        this._shaderValues.setInt(EffectMaterial.BLEND_DST, value);
	    }
	    get blendDst() {
	        return this._shaderValues.getInt(EffectMaterial.BLEND_DST);
	    }
	    set depthTest(value) {
	        this._shaderValues.setInt(EffectMaterial.DEPTH_TEST, value);
	    }
	    get depthTest() {
	        return this._shaderValues.getInt(EffectMaterial.DEPTH_TEST);
	    }
	    clone() {
	        var dest = new EffectMaterial();
	        this.cloneTo(dest);
	        return dest;
	    }
	}
	EffectMaterial.RENDERMODE_ADDTIVE = 0;
	EffectMaterial.RENDERMODE_ALPHABLENDED = 1;
	EffectMaterial.MAINTEXTURE = Shader3D.propertyNameToID("u_AlbedoTexture");
	EffectMaterial.TINTCOLOR = Shader3D.propertyNameToID("u_AlbedoColor");
	EffectMaterial.TILINGOFFSET = Shader3D.propertyNameToID("u_TilingOffset");
	EffectMaterial.CULL = Shader3D.propertyNameToID("s_Cull");
	EffectMaterial.BLEND = Shader3D.propertyNameToID("s_Blend");
	EffectMaterial.BLEND_SRC = Shader3D.propertyNameToID("s_BlendSrc");
	EffectMaterial.BLEND_DST = Shader3D.propertyNameToID("s_BlendDst");
	EffectMaterial.DEPTH_TEST = Shader3D.propertyNameToID("s_DepthTest");
	EffectMaterial.DEPTH_WRITE = Shader3D.propertyNameToID("s_DepthWrite");

	class ExtendTerrainMaterial extends BaseMaterial {
	    constructor() {
	        super();
	        this._enableLighting = true;
	        this.setShaderName("ExtendTerrain");
	        this.renderMode = ExtendTerrainMaterial.RENDERMODE_OPAQUE;
	    }
	    static __initDefine__() {
	        ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM1 = Shader3D.getDefineByName("ExtendTerrain_DETAIL_NUM1");
	        ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM2 = Shader3D.getDefineByName("ExtendTerrain_DETAIL_NUM2");
	        ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM3 = Shader3D.getDefineByName("ExtendTerrain_DETAIL_NUM3");
	        ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM4 = Shader3D.getDefineByName("ExtendTerrain_DETAIL_NUM4");
	        ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM5 = Shader3D.getDefineByName("ExtendTerrain_DETAIL_NUM5");
	    }
	    get splatAlphaTexture() {
	        return this._shaderValues.getTexture(ExtendTerrainMaterial.SPLATALPHATEXTURE);
	    }
	    set splatAlphaTexture(value) {
	        this._shaderValues.setTexture(ExtendTerrainMaterial.SPLATALPHATEXTURE, value);
	    }
	    set diffuseTexture1(value) {
	        this._shaderValues.setTexture(ExtendTerrainMaterial.DIFFUSETEXTURE1, value);
	        this._setDetailNum(1);
	    }
	    get diffuseTexture2() {
	        return this._shaderValues.getTexture(ExtendTerrainMaterial.DIFFUSETEXTURE2);
	    }
	    set diffuseTexture2(value) {
	        this._shaderValues.setTexture(ExtendTerrainMaterial.DIFFUSETEXTURE2, value);
	        this._setDetailNum(2);
	    }
	    get diffuseTexture3() {
	        return this._shaderValues.getTexture(ExtendTerrainMaterial.DIFFUSETEXTURE3);
	    }
	    set diffuseTexture3(value) {
	        this._shaderValues.setTexture(ExtendTerrainMaterial.DIFFUSETEXTURE3, value);
	        this._setDetailNum(3);
	    }
	    get diffuseTexture4() {
	        return this._shaderValues.getTexture(ExtendTerrainMaterial.DIFFUSETEXTURE4);
	    }
	    set diffuseTexture4(value) {
	        this._shaderValues.setTexture(ExtendTerrainMaterial.DIFFUSETEXTURE4, value);
	        this._setDetailNum(4);
	    }
	    get diffuseTexture5() {
	        return this._shaderValues.getTexture(ExtendTerrainMaterial.DIFFUSETEXTURE5);
	    }
	    set diffuseTexture5(value) {
	        this._shaderValues.setTexture(ExtendTerrainMaterial.DIFFUSETEXTURE5, value);
	        this._setDetailNum(5);
	    }
	    _setDetailNum(value) {
	        switch (value) {
	            case 1:
	                this._shaderValues.addDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM1);
	                this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM2);
	                this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM3);
	                this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM4);
	                this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM5);
	                break;
	            case 2:
	                this._shaderValues.addDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM2);
	                this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM1);
	                this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM3);
	                this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM4);
	                this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM5);
	                break;
	            case 3:
	                this._shaderValues.addDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM3);
	                this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM1);
	                this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM2);
	                this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM4);
	                this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM5);
	                break;
	            case 4:
	                this._shaderValues.addDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM4);
	                this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM1);
	                this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM2);
	                this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM3);
	                this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM5);
	                break;
	            case 5:
	                this._shaderValues.addDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM5);
	                this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM1);
	                this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM2);
	                this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM3);
	                this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM4);
	                break;
	        }
	    }
	    set diffuseScaleOffset1(scaleOffset1) {
	        this._shaderValues.setVector(ExtendTerrainMaterial.DIFFUSESCALEOFFSET1, scaleOffset1);
	    }
	    set diffuseScaleOffset2(scaleOffset2) {
	        this._shaderValues.setVector(ExtendTerrainMaterial.DIFFUSESCALEOFFSET2, scaleOffset2);
	    }
	    set diffuseScaleOffset3(scaleOffset3) {
	        this._shaderValues.setVector(ExtendTerrainMaterial.DIFFUSESCALEOFFSET3, scaleOffset3);
	    }
	    set diffuseScaleOffset4(scaleOffset4) {
	        this._shaderValues.setVector(ExtendTerrainMaterial.DIFFUSESCALEOFFSET4, scaleOffset4);
	    }
	    set diffuseScaleOffset5(scaleOffset5) {
	        this._shaderValues.setVector(ExtendTerrainMaterial.DIFFUSESCALEOFFSET5, scaleOffset5);
	    }
	    get enableLighting() {
	        return this._enableLighting;
	    }
	    set enableLighting(value) {
	        if (this._enableLighting !== value) {
	            if (value) {
	                this._disablePublicDefineDatas.remove(Scene3DShaderDeclaration.SHADERDEFINE_POINTLIGHT);
	                this._disablePublicDefineDatas.remove(Scene3DShaderDeclaration.SHADERDEFINE_SPOTLIGHT);
	                this._disablePublicDefineDatas.remove(Scene3DShaderDeclaration.SHADERDEFINE_DIRECTIONLIGHT);
	            }
	            else {
	                this._disablePublicDefineDatas.add(Scene3DShaderDeclaration.SHADERDEFINE_POINTLIGHT);
	                this._disablePublicDefineDatas.add(Scene3DShaderDeclaration.SHADERDEFINE_SPOTLIGHT);
	                this._disablePublicDefineDatas.add(Scene3DShaderDeclaration.SHADERDEFINE_DIRECTIONLIGHT);
	            }
	            this._enableLighting = value;
	        }
	    }
	    set renderMode(value) {
	        switch (value) {
	            case ExtendTerrainMaterial.RENDERMODE_OPAQUE:
	                this.renderQueue = BaseMaterial.RENDERQUEUE_OPAQUE;
	                this.depthWrite = true;
	                this.cull = RenderState.CULL_BACK;
	                this.blend = RenderState.BLEND_DISABLE;
	                this.depthTest = RenderState.DEPTHTEST_LESS;
	                break;
	            case ExtendTerrainMaterial.RENDERMODE_TRANSPARENT:
	                this.renderQueue = BaseMaterial.RENDERQUEUE_OPAQUE;
	                this.depthWrite = false;
	                this.cull = RenderState.CULL_BACK;
	                this.blend = RenderState.BLEND_ENABLE_ALL;
	                this.blendSrc = RenderState.BLENDPARAM_SRC_ALPHA;
	                this.blendDst = RenderState.BLENDPARAM_ONE_MINUS_SRC_ALPHA;
	                this.depthTest = RenderState.DEPTHTEST_LEQUAL;
	                break;
	            default:
	                throw new Error("ExtendTerrainMaterial:renderMode value error.");
	        }
	    }
	    set depthWrite(value) {
	        this._shaderValues.setBool(ExtendTerrainMaterial.DEPTH_WRITE, value);
	    }
	    get depthWrite() {
	        return this._shaderValues.getBool(ExtendTerrainMaterial.DEPTH_WRITE);
	    }
	    set cull(value) {
	        this._shaderValues.setInt(ExtendTerrainMaterial.CULL, value);
	    }
	    get cull() {
	        return this._shaderValues.getInt(ExtendTerrainMaterial.CULL);
	    }
	    set blend(value) {
	        this._shaderValues.setInt(ExtendTerrainMaterial.BLEND, value);
	    }
	    get blend() {
	        return this._shaderValues.getInt(ExtendTerrainMaterial.BLEND);
	    }
	    set blendSrc(value) {
	        this._shaderValues.setInt(ExtendTerrainMaterial.BLEND_SRC, value);
	    }
	    get blendSrc() {
	        return this._shaderValues.getInt(ExtendTerrainMaterial.BLEND_SRC);
	    }
	    set blendDst(value) {
	        this._shaderValues.setInt(ExtendTerrainMaterial.BLEND_DST, value);
	    }
	    get blendDst() {
	        return this._shaderValues.getInt(ExtendTerrainMaterial.BLEND_DST);
	    }
	    set depthTest(value) {
	        this._shaderValues.setInt(ExtendTerrainMaterial.DEPTH_TEST, value);
	    }
	    get depthTest() {
	        return this._shaderValues.getInt(ExtendTerrainMaterial.DEPTH_TEST);
	    }
	    clone() {
	        var dest = new ExtendTerrainMaterial();
	        this.cloneTo(dest);
	        return dest;
	    }
	}
	ExtendTerrainMaterial.RENDERMODE_OPAQUE = 1;
	ExtendTerrainMaterial.RENDERMODE_TRANSPARENT = 2;
	ExtendTerrainMaterial.SPLATALPHATEXTURE = Shader3D.propertyNameToID("u_SplatAlphaTexture");
	ExtendTerrainMaterial.DIFFUSETEXTURE1 = Shader3D.propertyNameToID("u_DiffuseTexture1");
	ExtendTerrainMaterial.DIFFUSETEXTURE2 = Shader3D.propertyNameToID("u_DiffuseTexture2");
	ExtendTerrainMaterial.DIFFUSETEXTURE3 = Shader3D.propertyNameToID("u_DiffuseTexture3");
	ExtendTerrainMaterial.DIFFUSETEXTURE4 = Shader3D.propertyNameToID("u_DiffuseTexture4");
	ExtendTerrainMaterial.DIFFUSETEXTURE5 = Shader3D.propertyNameToID("u_DiffuseTexture5");
	ExtendTerrainMaterial.DIFFUSESCALEOFFSET1 = Shader3D.propertyNameToID("u_DiffuseScaleOffset1");
	ExtendTerrainMaterial.DIFFUSESCALEOFFSET2 = Shader3D.propertyNameToID("u_DiffuseScaleOffset2");
	ExtendTerrainMaterial.DIFFUSESCALEOFFSET3 = Shader3D.propertyNameToID("u_DiffuseScaleOffset3");
	ExtendTerrainMaterial.DIFFUSESCALEOFFSET4 = Shader3D.propertyNameToID("u_DiffuseScaleOffset4");
	ExtendTerrainMaterial.DIFFUSESCALEOFFSET5 = Shader3D.propertyNameToID("u_DiffuseScaleOffset5");
	ExtendTerrainMaterial.CULL = Shader3D.propertyNameToID("s_Cull");
	ExtendTerrainMaterial.BLEND = Shader3D.propertyNameToID("s_Blend");
	ExtendTerrainMaterial.BLEND_SRC = Shader3D.propertyNameToID("s_BlendSrc");
	ExtendTerrainMaterial.BLEND_DST = Shader3D.propertyNameToID("s_BlendDst");
	ExtendTerrainMaterial.DEPTH_TEST = Shader3D.propertyNameToID("s_DepthTest");
	ExtendTerrainMaterial.DEPTH_WRITE = Shader3D.propertyNameToID("s_DepthWrite");

	class PBRSpecularMaterial extends BaseMaterial {
	    constructor() {
	        super();
	        this.setShaderName("PBRSpecular");
	        this._albedoColor = new Vector4(1.0, 1.0, 1.0, 1.0);
	        this._shaderValues.setVector(PBRSpecularMaterial.ALBEDOCOLOR, new Vector4(1.0, 1.0, 1.0, 1.0));
	        this._emissionColor = new Vector4(0.0, 0.0, 0.0, 0.0);
	        this._shaderValues.setVector(PBRSpecularMaterial.EMISSIONCOLOR, new Vector4(0.0, 0.0, 0.0, 0.0));
	        this._specularColor = new Vector4(0.2, 0.2, 0.2, 0.2);
	        this._shaderValues.setVector(PBRSpecularMaterial.SPECULARCOLOR, new Vector4(0.2, 0.2, 0.2, 0.2));
	        this._shaderValues.setNumber(PBRSpecularMaterial.SMOOTHNESS, 0.5);
	        this._shaderValues.setNumber(PBRSpecularMaterial.SMOOTHNESSSCALE, 1.0);
	        this._shaderValues.setNumber(PBRSpecularMaterial.SMOOTHNESSSOURCE, 0);
	        this._shaderValues.setNumber(PBRSpecularMaterial.OCCLUSIONSTRENGTH, 1.0);
	        this._shaderValues.setNumber(PBRSpecularMaterial.NORMALSCALE, 1.0);
	        this._shaderValues.setNumber(PBRSpecularMaterial.PARALLAXSCALE, 0.001);
	        this._shaderValues.setBool(PBRSpecularMaterial.ENABLEEMISSION, false);
	        this._shaderValues.setNumber(BaseMaterial.ALPHATESTVALUE, 0.5);
	        this.renderMode = PBRSpecularMaterial.RENDERMODE_OPAQUE;
	    }
	    static __initDefine__() {
	        PBRSpecularMaterial.SHADERDEFINE_ALBEDOTEXTURE = Shader3D.getDefineByName("ALBEDOTEXTURE");
	        PBRSpecularMaterial.SHADERDEFINE_SPECULARTEXTURE = Shader3D.getDefineByName("SPECULARTEXTURE");
	        PBRSpecularMaterial.SHADERDEFINE_SMOOTHNESSSOURCE_ALBEDOTEXTURE_ALPHA = Shader3D.getDefineByName("SMOOTHNESSSOURCE_ALBEDOTEXTURE_ALPHA");
	        PBRSpecularMaterial.SHADERDEFINE_NORMALTEXTURE = Shader3D.getDefineByName("NORMALTEXTURE");
	        PBRSpecularMaterial.SHADERDEFINE_PARALLAXTEXTURE = Shader3D.getDefineByName("PARALLAXTEXTURE");
	        PBRSpecularMaterial.SHADERDEFINE_OCCLUSIONTEXTURE = Shader3D.getDefineByName("OCCLUSIONTEXTURE");
	        PBRSpecularMaterial.SHADERDEFINE_EMISSION = Shader3D.getDefineByName("EMISSION");
	        PBRSpecularMaterial.SHADERDEFINE_EMISSIONTEXTURE = Shader3D.getDefineByName("EMISSIONTEXTURE");
	        PBRSpecularMaterial.SHADERDEFINE_TILINGOFFSET = Shader3D.getDefineByName("TILINGOFFSET");
	        PBRSpecularMaterial.SHADERDEFINE_ALPHAPREMULTIPLY = Shader3D.getDefineByName("ALPHAPREMULTIPLY");
	    }
	    get _ColorR() {
	        return this._albedoColor.x;
	    }
	    set _ColorR(value) {
	        this._albedoColor.x = value;
	        this.albedoColor = this._albedoColor;
	    }
	    get _ColorG() {
	        return this._albedoColor.y;
	    }
	    set _ColorG(value) {
	        this._albedoColor.y = value;
	        this.albedoColor = this._albedoColor;
	    }
	    get _ColorB() {
	        return this._albedoColor.z;
	    }
	    set _ColorB(value) {
	        this._albedoColor.z = value;
	        this.albedoColor = this._albedoColor;
	    }
	    get _ColorA() {
	        return this._albedoColor.w;
	    }
	    set _ColorA(value) {
	        this._albedoColor.w = value;
	        this.albedoColor = this._albedoColor;
	    }
	    get _SpecColorR() {
	        return this._specularColor.x;
	    }
	    set _SpecColorR(value) {
	        this._specularColor.x = value;
	        this.specularColor = this._specularColor;
	    }
	    get _SpecColorG() {
	        return this._specularColor.y;
	    }
	    set _SpecColorG(value) {
	        this._specularColor.y = value;
	        this.specularColor = this._specularColor;
	    }
	    get _SpecColorB() {
	        return this._specularColor.z;
	    }
	    set _SpecColorB(value) {
	        this._specularColor.z = value;
	        this.specularColor = this._specularColor;
	    }
	    get _SpecColorA() {
	        return this._specularColor.w;
	    }
	    set _SpecColorA(value) {
	        this._specularColor.w = value;
	        this.specularColor = this._specularColor;
	    }
	    get _Glossiness() {
	        return this._shaderValues.getNumber(PBRSpecularMaterial.SMOOTHNESS);
	    }
	    set _Glossiness(value) {
	        this._shaderValues.setNumber(PBRSpecularMaterial.SMOOTHNESS, value);
	    }
	    get _GlossMapScale() {
	        return this._shaderValues.getNumber(PBRSpecularMaterial.SMOOTHNESSSCALE);
	    }
	    set _GlossMapScale(value) {
	        this._shaderValues.setNumber(PBRSpecularMaterial.SMOOTHNESSSCALE, value);
	    }
	    get _BumpScale() {
	        return this._shaderValues.getNumber(PBRSpecularMaterial.NORMALSCALE);
	    }
	    set _BumpScale(value) {
	        this._shaderValues.setNumber(PBRSpecularMaterial.NORMALSCALE, value);
	    }
	    get _Parallax() {
	        return this._shaderValues.getNumber(PBRSpecularMaterial.PARALLAXSCALE);
	    }
	    set _Parallax(value) {
	        this._shaderValues.setNumber(PBRSpecularMaterial.PARALLAXSCALE, value);
	    }
	    get _OcclusionStrength() {
	        return this._shaderValues.getNumber(PBRSpecularMaterial.OCCLUSIONSTRENGTH);
	    }
	    set _OcclusionStrength(value) {
	        this._shaderValues.setNumber(PBRSpecularMaterial.OCCLUSIONSTRENGTH, value);
	    }
	    get _EmissionColorR() {
	        return this._emissionColor.x;
	    }
	    set _EmissionColorR(value) {
	        this._emissionColor.x = value;
	        this.emissionColor = this._emissionColor;
	    }
	    get _EmissionColorG() {
	        return this._emissionColor.y;
	    }
	    set _EmissionColorG(value) {
	        this._emissionColor.y = value;
	        this.emissionColor = this._emissionColor;
	    }
	    get _EmissionColorB() {
	        return this._emissionColor.z;
	    }
	    set _EmissionColorB(value) {
	        this._emissionColor.z = value;
	        this.emissionColor = this._emissionColor;
	    }
	    get _EmissionColorA() {
	        return this._emissionColor.w;
	    }
	    set _EmissionColorA(value) {
	        this._emissionColor.w = value;
	        this.emissionColor = this._emissionColor;
	    }
	    get _MainTex_STX() {
	        return this._shaderValues.getVector(PBRSpecularMaterial.TILINGOFFSET).x;
	    }
	    set _MainTex_STX(x) {
	        var tilOff = this._shaderValues.getVector(PBRSpecularMaterial.TILINGOFFSET);
	        tilOff.x = x;
	        this.tilingOffset = tilOff;
	    }
	    get _MainTex_STY() {
	        return this._shaderValues.getVector(PBRSpecularMaterial.TILINGOFFSET).y;
	    }
	    set _MainTex_STY(y) {
	        var tilOff = this._shaderValues.getVector(PBRSpecularMaterial.TILINGOFFSET);
	        tilOff.y = y;
	        this.tilingOffset = tilOff;
	    }
	    get _MainTex_STZ() {
	        return this._shaderValues.getVector(PBRSpecularMaterial.TILINGOFFSET).z;
	    }
	    set _MainTex_STZ(z) {
	        var tilOff = this._shaderValues.getVector(PBRSpecularMaterial.TILINGOFFSET);
	        tilOff.z = z;
	        this.tilingOffset = tilOff;
	    }
	    get _MainTex_STW() {
	        return this._shaderValues.getVector(PBRSpecularMaterial.TILINGOFFSET).w;
	    }
	    set _MainTex_STW(w) {
	        var tilOff = this._shaderValues.getVector(PBRSpecularMaterial.TILINGOFFSET);
	        tilOff.w = w;
	        this.tilingOffset = tilOff;
	    }
	    get _Cutoff() {
	        return this.alphaTestValue;
	    }
	    set _Cutoff(value) {
	        this.alphaTestValue = value;
	    }
	    get albedoColorR() {
	        return this._ColorR;
	    }
	    set albedoColorR(value) {
	        this._ColorR = value;
	    }
	    get albedoColorG() {
	        return this._ColorG;
	    }
	    set albedoColorG(value) {
	        this._ColorG = value;
	    }
	    get albedoColorB() {
	        return this._ColorB;
	    }
	    set albedoColorB(value) {
	        this._ColorB = value;
	    }
	    get albedoColorA() {
	        return this._ColorA;
	    }
	    set albedoColorA(value) {
	        this._ColorA = value;
	    }
	    get albedoColor() {
	        return this._albedoColor;
	    }
	    set albedoColor(value) {
	        this._albedoColor = value;
	        this._shaderValues.setVector(PBRSpecularMaterial.ALBEDOCOLOR, value);
	    }
	    get albedoTexture() {
	        return this._shaderValues.getTexture(PBRSpecularMaterial.ALBEDOTEXTURE);
	    }
	    set albedoTexture(value) {
	        if (value) {
	            this._shaderValues.addDefine(PBRSpecularMaterial.SHADERDEFINE_ALBEDOTEXTURE);
	        }
	        else {
	            this._shaderValues.removeDefine(PBRSpecularMaterial.SHADERDEFINE_ALBEDOTEXTURE);
	        }
	        this._shaderValues.setTexture(PBRSpecularMaterial.ALBEDOTEXTURE, value);
	    }
	    get normalTexture() {
	        return this._shaderValues.getTexture(PBRSpecularMaterial.NORMALTEXTURE);
	    }
	    set normalTexture(value) {
	        if (value) {
	            this._shaderValues.addDefine(PBRSpecularMaterial.SHADERDEFINE_NORMALTEXTURE);
	        }
	        else {
	            this._shaderValues.removeDefine(PBRSpecularMaterial.SHADERDEFINE_NORMALTEXTURE);
	        }
	        this._shaderValues.setTexture(PBRSpecularMaterial.NORMALTEXTURE, value);
	    }
	    get normalTextureScale() {
	        return this._BumpScale;
	    }
	    set normalTextureScale(value) {
	        this._BumpScale = value;
	    }
	    get parallaxTexture() {
	        return this._shaderValues.getTexture(PBRSpecularMaterial.PARALLAXTEXTURE);
	    }
	    set parallaxTexture(value) {
	        if (value) {
	            this._shaderValues.addDefine(PBRSpecularMaterial.SHADERDEFINE_PARALLAXTEXTURE);
	        }
	        else {
	            this._shaderValues.removeDefine(PBRSpecularMaterial.SHADERDEFINE_PARALLAXTEXTURE);
	        }
	        this._shaderValues.setTexture(PBRSpecularMaterial.PARALLAXTEXTURE, value);
	    }
	    get parallaxTextureScale() {
	        return this._Parallax;
	    }
	    set parallaxTextureScale(value) {
	        this._Parallax = Math.max(0.005, Math.min(0.08, value));
	    }
	    get occlusionTexture() {
	        return this._shaderValues.getTexture(PBRSpecularMaterial.OCCLUSIONTEXTURE);
	    }
	    set occlusionTexture(value) {
	        if (value) {
	            this._shaderValues.addDefine(PBRSpecularMaterial.SHADERDEFINE_OCCLUSIONTEXTURE);
	        }
	        else {
	            this._shaderValues.removeDefine(PBRSpecularMaterial.SHADERDEFINE_OCCLUSIONTEXTURE);
	        }
	        this._shaderValues.setTexture(PBRSpecularMaterial.OCCLUSIONTEXTURE, value);
	    }
	    get occlusionTextureStrength() {
	        return this._OcclusionStrength;
	    }
	    set occlusionTextureStrength(value) {
	        this._OcclusionStrength = Math.max(0.0, Math.min(1.0, value));
	    }
	    get specularTexture() {
	        return this._shaderValues.getTexture(PBRSpecularMaterial.SPECULARTEXTURE);
	    }
	    set specularTexture(value) {
	        if (value) {
	            this._shaderValues.addDefine(PBRSpecularMaterial.SHADERDEFINE_SPECULARTEXTURE);
	        }
	        else {
	            this._shaderValues.removeDefine(PBRSpecularMaterial.SHADERDEFINE_SPECULARTEXTURE);
	        }
	        this._shaderValues.setTexture(PBRSpecularMaterial.SPECULARTEXTURE, value);
	    }
	    get specularColorR() {
	        return this._SpecColorR;
	    }
	    set specularColorR(value) {
	        this._SpecColorR = value;
	    }
	    get specularColorG() {
	        return this._SpecColorG;
	    }
	    set specularColorG(value) {
	        this._SpecColorG = value;
	    }
	    get specularColorB() {
	        return this._SpecColorB;
	    }
	    set specularColorB(value) {
	        this._SpecColorB = value;
	    }
	    get specularColorA() {
	        return this._SpecColorA;
	    }
	    set specularColorA(value) {
	        this._SpecColorA = value;
	    }
	    get specularColor() {
	        return this._shaderValues.getVector(PBRSpecularMaterial.SPECULARCOLOR);
	    }
	    set specularColor(value) {
	        this._shaderValues.setVector(PBRSpecularMaterial.SPECULARCOLOR, value);
	    }
	    get smoothness() {
	        return this._Glossiness;
	    }
	    set smoothness(value) {
	        this._Glossiness = Math.max(0.0, Math.min(1.0, value));
	    }
	    get smoothnessTextureScale() {
	        return this._GlossMapScale;
	    }
	    set smoothnessTextureScale(value) {
	        this._GlossMapScale = Math.max(0.0, Math.min(1.0, value));
	    }
	    get smoothnessSource() {
	        return this._shaderValues.getInt(PBRSpecularMaterial.SMOOTHNESSSOURCE);
	    }
	    set smoothnessSource(value) {
	        if (value) {
	            this._shaderValues.addDefine(PBRSpecularMaterial.SHADERDEFINE_SMOOTHNESSSOURCE_ALBEDOTEXTURE_ALPHA);
	            this._shaderValues.setInt(PBRSpecularMaterial.SMOOTHNESSSOURCE, 1);
	        }
	        else {
	            this._shaderValues.removeDefine(PBRSpecularMaterial.SHADERDEFINE_SMOOTHNESSSOURCE_ALBEDOTEXTURE_ALPHA);
	            this._shaderValues.setInt(PBRSpecularMaterial.SMOOTHNESSSOURCE, 0);
	        }
	    }
	    get enableEmission() {
	        return this._shaderValues.getBool(PBRSpecularMaterial.ENABLEEMISSION);
	    }
	    set enableEmission(value) {
	        if (value)
	            this._shaderValues.addDefine(PBRSpecularMaterial.SHADERDEFINE_EMISSION);
	        else {
	            this._shaderValues.removeDefine(PBRSpecularMaterial.SHADERDEFINE_EMISSION);
	        }
	        this._shaderValues.setBool(PBRSpecularMaterial.ENABLEEMISSION, value);
	    }
	    get emissionColor() {
	        return this._shaderValues.getVector(PBRSpecularMaterial.EMISSIONCOLOR);
	    }
	    set emissionColor(value) {
	        this._shaderValues.setVector(PBRSpecularMaterial.EMISSIONCOLOR, value);
	    }
	    get emissionTexture() {
	        return this._shaderValues.getTexture(PBRSpecularMaterial.EMISSIONTEXTURE);
	    }
	    set emissionTexture(value) {
	        if (value)
	            this._shaderValues.addDefine(PBRSpecularMaterial.SHADERDEFINE_EMISSIONTEXTURE);
	        else
	            this._shaderValues.removeDefine(PBRSpecularMaterial.SHADERDEFINE_EMISSIONTEXTURE);
	        this._shaderValues.setTexture(PBRSpecularMaterial.EMISSIONTEXTURE, value);
	    }
	    get enableReflection() {
	        return this._shaderValues.getBool(PBRSpecularMaterial.ENABLEREFLECT);
	    }
	    set enableReflection(value) {
	        this._shaderValues.setBool(PBRSpecularMaterial.ENABLEREFLECT, true);
	        if (value)
	            this._disablePublicDefineDatas.remove(Scene3DShaderDeclaration.SHADERDEFINE_REFLECTMAP);
	        else
	            this._disablePublicDefineDatas.add(Scene3DShaderDeclaration.SHADERDEFINE_REFLECTMAP);
	    }
	    get tilingOffsetX() {
	        return this._MainTex_STX;
	    }
	    set tilingOffsetX(x) {
	        this._MainTex_STX = x;
	    }
	    get tilingOffsetY() {
	        return this._MainTex_STY;
	    }
	    set tilingOffsetY(y) {
	        this._MainTex_STY = y;
	    }
	    get tilingOffsetZ() {
	        return this._MainTex_STZ;
	    }
	    set tilingOffsetZ(z) {
	        this._MainTex_STZ = z;
	    }
	    get tilingOffsetW() {
	        return this._MainTex_STW;
	    }
	    set tilingOffsetW(w) {
	        this._MainTex_STW = w;
	    }
	    get tilingOffset() {
	        return this._shaderValues.getVector(PBRSpecularMaterial.TILINGOFFSET);
	    }
	    set tilingOffset(value) {
	        if (value) {
	            if (value.x != 1 || value.y != 1 || value.z != 0 || value.w != 0)
	                this._shaderValues.addDefine(PBRSpecularMaterial.SHADERDEFINE_TILINGOFFSET);
	            else
	                this._shaderValues.removeDefine(PBRSpecularMaterial.SHADERDEFINE_TILINGOFFSET);
	        }
	        else {
	            this._shaderValues.removeDefine(PBRSpecularMaterial.SHADERDEFINE_TILINGOFFSET);
	        }
	        this._shaderValues.setVector(PBRSpecularMaterial.TILINGOFFSET, value);
	    }
	    set renderMode(value) {
	        switch (value) {
	            case PBRSpecularMaterial.RENDERMODE_OPAQUE:
	                this.alphaTest = false;
	                this.renderQueue = BaseMaterial.RENDERQUEUE_OPAQUE;
	                this.depthWrite = true;
	                this.cull = RenderState.CULL_BACK;
	                this.blend = RenderState.BLEND_DISABLE;
	                this.depthTest = RenderState.DEPTHTEST_LESS;
	                this._shaderValues.removeDefine(PBRSpecularMaterial.SHADERDEFINE_ALPHAPREMULTIPLY);
	                break;
	            case PBRSpecularMaterial.RENDERMODE_CUTOUT:
	                this.renderQueue = BaseMaterial.RENDERQUEUE_ALPHATEST;
	                this.alphaTest = true;
	                this.depthWrite = true;
	                this.cull = RenderState.CULL_BACK;
	                this.blend = RenderState.BLEND_DISABLE;
	                this.depthTest = RenderState.DEPTHTEST_LESS;
	                this._shaderValues.removeDefine(PBRSpecularMaterial.SHADERDEFINE_ALPHAPREMULTIPLY);
	                break;
	            case PBRSpecularMaterial.RENDERMODE_FADE:
	                this.renderQueue = BaseMaterial.RENDERQUEUE_TRANSPARENT;
	                this.alphaTest = false;
	                this.depthWrite = false;
	                this.cull = RenderState.CULL_BACK;
	                this.blend = RenderState.BLEND_ENABLE_ALL;
	                this.blendSrc = RenderState.BLENDPARAM_SRC_ALPHA;
	                this.blendDst = RenderState.BLENDPARAM_ONE_MINUS_SRC_ALPHA;
	                this.depthTest = RenderState.DEPTHTEST_LESS;
	                this._shaderValues.removeDefine(PBRSpecularMaterial.SHADERDEFINE_ALPHAPREMULTIPLY);
	                break;
	            case PBRSpecularMaterial.RENDERMODE_TRANSPARENT:
	                this.renderQueue = BaseMaterial.RENDERQUEUE_TRANSPARENT;
	                this.alphaTest = false;
	                this.depthWrite = false;
	                this.cull = RenderState.CULL_BACK;
	                this.blend = RenderState.BLEND_ENABLE_ALL;
	                this.blendSrc = RenderState.BLENDPARAM_ONE;
	                this.blendDst = RenderState.BLENDPARAM_ONE_MINUS_SRC_ALPHA;
	                this.depthTest = RenderState.DEPTHTEST_LESS;
	                this._shaderValues.addDefine(PBRSpecularMaterial.SHADERDEFINE_ALPHAPREMULTIPLY);
	                break;
	            default:
	                throw new Error("PBRSpecularMaterial : renderMode value error.");
	        }
	    }
	    get depthWrite() {
	        return this._shaderValues.getBool(PBRSpecularMaterial.DEPTH_WRITE);
	    }
	    set depthWrite(value) {
	        this._shaderValues.setBool(PBRSpecularMaterial.DEPTH_WRITE, value);
	    }
	    get cull() {
	        return this._shaderValues.getInt(PBRSpecularMaterial.CULL);
	    }
	    set cull(value) {
	        this._shaderValues.setInt(PBRSpecularMaterial.CULL, value);
	    }
	    get blend() {
	        return this._shaderValues.getInt(PBRSpecularMaterial.BLEND);
	    }
	    set blend(value) {
	        this._shaderValues.setInt(PBRSpecularMaterial.BLEND, value);
	    }
	    get blendSrc() {
	        return this._shaderValues.getInt(PBRSpecularMaterial.BLEND_SRC);
	    }
	    set blendSrc(value) {
	        this._shaderValues.setInt(PBRSpecularMaterial.BLEND_SRC, value);
	    }
	    get blendDst() {
	        return this._shaderValues.getInt(PBRSpecularMaterial.BLEND_DST);
	    }
	    set blendDst(value) {
	        this._shaderValues.setInt(PBRSpecularMaterial.BLEND_DST, value);
	    }
	    get depthTest() {
	        return this._shaderValues.getInt(PBRSpecularMaterial.DEPTH_TEST);
	    }
	    set depthTest(value) {
	        this._shaderValues.setInt(PBRSpecularMaterial.DEPTH_TEST, value);
	    }
	    clone() {
	        var dest = new PBRSpecularMaterial();
	        this.cloneTo(dest);
	        return dest;
	    }
	    cloneTo(destObject) {
	        super.cloneTo(destObject);
	        var destMaterial = destObject;
	        this._albedoColor.cloneTo(destMaterial._albedoColor);
	        this._specularColor.cloneTo(destMaterial._specularColor);
	        this._emissionColor.cloneTo(destMaterial._emissionColor);
	    }
	}
	PBRSpecularMaterial.SmoothnessSource_SpecularTexture_Alpha = 0;
	PBRSpecularMaterial.SmoothnessSource_AlbedoTexture_Alpha = 1;
	PBRSpecularMaterial.RENDERMODE_OPAQUE = 0;
	PBRSpecularMaterial.RENDERMODE_CUTOUT = 1;
	PBRSpecularMaterial.RENDERMODE_FADE = 2;
	PBRSpecularMaterial.RENDERMODE_TRANSPARENT = 3;
	PBRSpecularMaterial.ALBEDOTEXTURE = Shader3D.propertyNameToID("u_AlbedoTexture");
	PBRSpecularMaterial.SPECULARTEXTURE = Shader3D.propertyNameToID("u_SpecularTexture");
	PBRSpecularMaterial.NORMALTEXTURE = Shader3D.propertyNameToID("u_NormalTexture");
	PBRSpecularMaterial.PARALLAXTEXTURE = Shader3D.propertyNameToID("u_ParallaxTexture");
	PBRSpecularMaterial.OCCLUSIONTEXTURE = Shader3D.propertyNameToID("u_OcclusionTexture");
	PBRSpecularMaterial.EMISSIONTEXTURE = Shader3D.propertyNameToID("u_EmissionTexture");
	PBRSpecularMaterial.ALBEDOCOLOR = Shader3D.propertyNameToID("u_AlbedoColor");
	PBRSpecularMaterial.SPECULARCOLOR = Shader3D.propertyNameToID("u_SpecularColor");
	PBRSpecularMaterial.EMISSIONCOLOR = Shader3D.propertyNameToID("u_EmissionColor");
	PBRSpecularMaterial.SMOOTHNESS = Shader3D.propertyNameToID("u_smoothness");
	PBRSpecularMaterial.SMOOTHNESSSCALE = Shader3D.propertyNameToID("u_smoothnessScale");
	PBRSpecularMaterial.SMOOTHNESSSOURCE = -1;
	PBRSpecularMaterial.OCCLUSIONSTRENGTH = Shader3D.propertyNameToID("u_occlusionStrength");
	PBRSpecularMaterial.NORMALSCALE = Shader3D.propertyNameToID("u_normalScale");
	PBRSpecularMaterial.PARALLAXSCALE = Shader3D.propertyNameToID("u_parallaxScale");
	PBRSpecularMaterial.ENABLEEMISSION = -1;
	PBRSpecularMaterial.ENABLEREFLECT = -1;
	PBRSpecularMaterial.TILINGOFFSET = Shader3D.propertyNameToID("u_TilingOffset");
	PBRSpecularMaterial.CULL = Shader3D.propertyNameToID("s_Cull");
	PBRSpecularMaterial.BLEND = Shader3D.propertyNameToID("s_Blend");
	PBRSpecularMaterial.BLEND_SRC = Shader3D.propertyNameToID("s_BlendSrc");
	PBRSpecularMaterial.BLEND_DST = Shader3D.propertyNameToID("s_BlendDst");
	PBRSpecularMaterial.DEPTH_TEST = Shader3D.propertyNameToID("s_DepthTest");
	PBRSpecularMaterial.DEPTH_WRITE = Shader3D.propertyNameToID("s_DepthWrite");

	class PBRStandardMaterial extends BaseMaterial {
	    constructor() {
	        super();
	        this.setShaderName("PBRStandard");
	        this._albedoColor = new Vector4(1.0, 1.0, 1.0, 1.0);
	        this._shaderValues.setVector(PBRStandardMaterial.ALBEDOCOLOR, new Vector4(1.0, 1.0, 1.0, 1.0));
	        this._emissionColor = new Vector4(0.0, 0.0, 0.0, 0.0);
	        this._shaderValues.setVector(PBRStandardMaterial.EMISSIONCOLOR, new Vector4(0.0, 0.0, 0.0, 0.0));
	        this._shaderValues.setNumber(PBRStandardMaterial.METALLIC, 0.0);
	        this._shaderValues.setNumber(PBRStandardMaterial.SMOOTHNESS, 0.5);
	        this._shaderValues.setNumber(PBRStandardMaterial.SMOOTHNESSSCALE, 1.0);
	        this._shaderValues.setNumber(PBRStandardMaterial.SMOOTHNESSSOURCE, 0);
	        this._shaderValues.setNumber(PBRStandardMaterial.OCCLUSIONSTRENGTH, 1.0);
	        this._shaderValues.setNumber(PBRStandardMaterial.NORMALSCALE, 1.0);
	        this._shaderValues.setNumber(PBRStandardMaterial.PARALLAXSCALE, 0.001);
	        this._shaderValues.setBool(PBRStandardMaterial.ENABLEEMISSION, false);
	        this._shaderValues.setBool(PBRStandardMaterial.ENABLEREFLECT, true);
	        this._shaderValues.setNumber(BaseMaterial.ALPHATESTVALUE, 0.5);
	        this._disablePublicDefineDatas.remove(Scene3DShaderDeclaration.SHADERDEFINE_REFLECTMAP);
	        this.renderMode = PBRStandardMaterial.RENDERMODE_OPAQUE;
	    }
	    static __initDefine__() {
	        PBRStandardMaterial.SHADERDEFINE_ALBEDOTEXTURE = Shader3D.getDefineByName("ALBEDOTEXTURE");
	        PBRStandardMaterial.SHADERDEFINE_METALLICGLOSSTEXTURE = Shader3D.getDefineByName("METALLICGLOSSTEXTURE");
	        PBRStandardMaterial.SHADERDEFINE_SMOOTHNESSSOURCE_ALBEDOTEXTURE_ALPHA = Shader3D.getDefineByName("SMOOTHNESSSOURCE_ALBEDOTEXTURE_ALPHA");
	        PBRStandardMaterial.SHADERDEFINE_NORMALTEXTURE = Shader3D.getDefineByName("NORMALTEXTURE");
	        PBRStandardMaterial.SHADERDEFINE_PARALLAXTEXTURE = Shader3D.getDefineByName("PARALLAXTEXTURE");
	        PBRStandardMaterial.SHADERDEFINE_OCCLUSIONTEXTURE = Shader3D.getDefineByName("OCCLUSIONTEXTURE");
	        PBRStandardMaterial.SHADERDEFINE_EMISSION = Shader3D.getDefineByName("EMISSION");
	        PBRStandardMaterial.SHADERDEFINE_EMISSIONTEXTURE = Shader3D.getDefineByName("EMISSIONTEXTURE");
	        PBRStandardMaterial.SHADERDEFINE_REFLECTMAP = Shader3D.getDefineByName("REFLECTMAP");
	        PBRStandardMaterial.SHADERDEFINE_TILINGOFFSET = Shader3D.getDefineByName("TILINGOFFSET");
	        PBRStandardMaterial.SHADERDEFINE_ALPHAPREMULTIPLY = Shader3D.getDefineByName("ALPHAPREMULTIPLY");
	    }
	    get _ColorR() {
	        return this._albedoColor.x;
	    }
	    set _ColorR(value) {
	        this._albedoColor.x = value;
	        this.albedoColor = this._albedoColor;
	    }
	    get _ColorG() {
	        return this._albedoColor.y;
	    }
	    set _ColorG(value) {
	        this._albedoColor.y = value;
	        this.albedoColor = this._albedoColor;
	    }
	    get _ColorB() {
	        return this._albedoColor.z;
	    }
	    set _ColorB(value) {
	        this._albedoColor.z = value;
	        this.albedoColor = this._albedoColor;
	    }
	    get _ColorA() {
	        return this._albedoColor.w;
	    }
	    set _ColorA(value) {
	        this._albedoColor.w = value;
	        this.albedoColor = this._albedoColor;
	    }
	    get _Metallic() {
	        return this._shaderValues.getNumber(PBRStandardMaterial.METALLIC);
	    }
	    set _Metallic(value) {
	        this._shaderValues.setNumber(PBRStandardMaterial.METALLIC, value);
	    }
	    get _Glossiness() {
	        return this._shaderValues.getNumber(PBRStandardMaterial.SMOOTHNESS);
	    }
	    set _Glossiness(value) {
	        this._shaderValues.setNumber(PBRStandardMaterial.SMOOTHNESS, value);
	    }
	    get _GlossMapScale() {
	        return this._shaderValues.getNumber(PBRStandardMaterial.SMOOTHNESSSCALE);
	    }
	    set _GlossMapScale(value) {
	        this._shaderValues.setNumber(PBRStandardMaterial.SMOOTHNESSSCALE, value);
	    }
	    get _BumpScale() {
	        return this._shaderValues.getNumber(PBRStandardMaterial.NORMALSCALE);
	    }
	    set _BumpScale(value) {
	        this._shaderValues.setNumber(PBRStandardMaterial.NORMALSCALE, value);
	    }
	    get _Parallax() {
	        return this._shaderValues.getNumber(PBRStandardMaterial.PARALLAXSCALE);
	    }
	    set _Parallax(value) {
	        this._shaderValues.setNumber(PBRStandardMaterial.PARALLAXSCALE, value);
	    }
	    get _OcclusionStrength() {
	        return this._shaderValues.getNumber(PBRStandardMaterial.OCCLUSIONSTRENGTH);
	    }
	    set _OcclusionStrength(value) {
	        this._shaderValues.setNumber(PBRStandardMaterial.OCCLUSIONSTRENGTH, value);
	    }
	    get _EmissionColorR() {
	        return this._emissionColor.x;
	    }
	    set _EmissionColorR(value) {
	        this._emissionColor.x = value;
	        this.emissionColor = this._emissionColor;
	    }
	    get _EmissionColorG() {
	        return this._emissionColor.y;
	    }
	    set _EmissionColorG(value) {
	        this._emissionColor.y = value;
	        this.emissionColor = this._emissionColor;
	    }
	    get _EmissionColorB() {
	        return this._emissionColor.z;
	    }
	    set _EmissionColorB(value) {
	        this._emissionColor.z = value;
	        this.emissionColor = this._emissionColor;
	    }
	    get _EmissionColorA() {
	        return this._emissionColor.w;
	    }
	    set _EmissionColorA(value) {
	        this._emissionColor.w = value;
	        this.emissionColor = this._emissionColor;
	    }
	    get _MainTex_STX() {
	        return this._shaderValues.getVector(PBRStandardMaterial.TILINGOFFSET).x;
	    }
	    set _MainTex_STX(x) {
	        var tilOff = this._shaderValues.getVector(PBRStandardMaterial.TILINGOFFSET);
	        tilOff.x = x;
	        this.tilingOffset = tilOff;
	    }
	    get _MainTex_STY() {
	        return this._shaderValues.getVector(PBRStandardMaterial.TILINGOFFSET).y;
	    }
	    set _MainTex_STY(y) {
	        var tilOff = this._shaderValues.getVector(PBRStandardMaterial.TILINGOFFSET);
	        tilOff.y = y;
	        this.tilingOffset = tilOff;
	    }
	    get _MainTex_STZ() {
	        return this._shaderValues.getVector(PBRStandardMaterial.TILINGOFFSET).z;
	    }
	    set _MainTex_STZ(z) {
	        var tilOff = this._shaderValues.getVector(PBRStandardMaterial.TILINGOFFSET);
	        tilOff.z = z;
	        this.tilingOffset = tilOff;
	    }
	    get _MainTex_STW() {
	        return this._shaderValues.getVector(PBRStandardMaterial.TILINGOFFSET).w;
	    }
	    set _MainTex_STW(w) {
	        var tilOff = this._shaderValues.getVector(PBRStandardMaterial.TILINGOFFSET);
	        tilOff.w = w;
	        this.tilingOffset = tilOff;
	    }
	    get _Cutoff() {
	        return this.alphaTestValue;
	    }
	    set _Cutoff(value) {
	        this.alphaTestValue = value;
	    }
	    get albedoColorR() {
	        return this._ColorR;
	    }
	    set albedoColorR(value) {
	        this._ColorR = value;
	    }
	    get albedoColorG() {
	        return this._ColorG;
	    }
	    set albedoColorG(value) {
	        this._ColorG = value;
	    }
	    get albedoColorB() {
	        return this._ColorB;
	    }
	    set albedoColorB(value) {
	        this._ColorB = value;
	    }
	    get albedoColorA() {
	        return this._ColorA;
	    }
	    set albedoColorA(value) {
	        this._ColorA = value;
	    }
	    get albedoColor() {
	        return this._albedoColor;
	    }
	    set albedoColor(value) {
	        this._albedoColor = value;
	        this._shaderValues.setVector(PBRStandardMaterial.ALBEDOCOLOR, value);
	    }
	    get albedoTexture() {
	        return this._shaderValues.getTexture(PBRStandardMaterial.ALBEDOTEXTURE);
	    }
	    set albedoTexture(value) {
	        if (value) {
	            this._shaderValues.addDefine(PBRStandardMaterial.SHADERDEFINE_ALBEDOTEXTURE);
	        }
	        else {
	            this._shaderValues.removeDefine(PBRStandardMaterial.SHADERDEFINE_ALBEDOTEXTURE);
	        }
	        this._shaderValues.setTexture(PBRStandardMaterial.ALBEDOTEXTURE, value);
	    }
	    get normalTexture() {
	        return this._shaderValues.getTexture(PBRStandardMaterial.NORMALTEXTURE);
	    }
	    set normalTexture(value) {
	        if (value) {
	            this._shaderValues.addDefine(PBRStandardMaterial.SHADERDEFINE_NORMALTEXTURE);
	        }
	        else {
	            this._shaderValues.removeDefine(PBRStandardMaterial.SHADERDEFINE_NORMALTEXTURE);
	        }
	        this._shaderValues.setTexture(PBRStandardMaterial.NORMALTEXTURE, value);
	    }
	    get normalTextureScale() {
	        return this._BumpScale;
	    }
	    set normalTextureScale(value) {
	        this._BumpScale = value;
	    }
	    get parallaxTexture() {
	        return this._shaderValues.getTexture(PBRStandardMaterial.PARALLAXTEXTURE);
	    }
	    set parallaxTexture(value) {
	        if (value) {
	            this._shaderValues.addDefine(PBRStandardMaterial.SHADERDEFINE_PARALLAXTEXTURE);
	        }
	        else {
	            this._shaderValues.removeDefine(PBRStandardMaterial.SHADERDEFINE_PARALLAXTEXTURE);
	        }
	        this._shaderValues.setTexture(PBRStandardMaterial.PARALLAXTEXTURE, value);
	    }
	    get parallaxTextureScale() {
	        return this._Parallax;
	    }
	    set parallaxTextureScale(value) {
	        this._Parallax = Math.max(0.005, Math.min(0.08, value));
	    }
	    get occlusionTexture() {
	        return this._shaderValues.getTexture(PBRStandardMaterial.OCCLUSIONTEXTURE);
	    }
	    set occlusionTexture(value) {
	        if (value) {
	            this._shaderValues.addDefine(PBRStandardMaterial.SHADERDEFINE_OCCLUSIONTEXTURE);
	        }
	        else {
	            this._shaderValues.removeDefine(PBRStandardMaterial.SHADERDEFINE_OCCLUSIONTEXTURE);
	        }
	        this._shaderValues.setTexture(PBRStandardMaterial.OCCLUSIONTEXTURE, value);
	    }
	    get occlusionTextureStrength() {
	        return this._OcclusionStrength;
	    }
	    set occlusionTextureStrength(value) {
	        this._OcclusionStrength = Math.max(0.0, Math.min(1.0, value));
	    }
	    get metallicGlossTexture() {
	        return this._shaderValues.getTexture(PBRStandardMaterial.METALLICGLOSSTEXTURE);
	    }
	    set metallicGlossTexture(value) {
	        if (value) {
	            this._shaderValues.addDefine(PBRStandardMaterial.SHADERDEFINE_METALLICGLOSSTEXTURE);
	        }
	        else {
	            this._shaderValues.removeDefine(PBRStandardMaterial.SHADERDEFINE_METALLICGLOSSTEXTURE);
	        }
	        this._shaderValues.setTexture(PBRStandardMaterial.METALLICGLOSSTEXTURE, value);
	    }
	    get metallic() {
	        return this._Metallic;
	    }
	    set metallic(value) {
	        this._Metallic = Math.max(0.0, Math.min(1.0, value));
	    }
	    get smoothness() {
	        return this._Glossiness;
	    }
	    set smoothness(value) {
	        this._Glossiness = Math.max(0.0, Math.min(1.0, value));
	    }
	    get smoothnessTextureScale() {
	        return this._GlossMapScale;
	    }
	    set smoothnessTextureScale(value) {
	        this._GlossMapScale = Math.max(0.0, Math.min(1.0, value));
	    }
	    get smoothnessSource() {
	        return this._shaderValues.getInt(PBRStandardMaterial.SMOOTHNESSSOURCE);
	    }
	    set smoothnessSource(value) {
	        if (value) {
	            this._shaderValues.addDefine(PBRStandardMaterial.SHADERDEFINE_SMOOTHNESSSOURCE_ALBEDOTEXTURE_ALPHA);
	            this._shaderValues.setInt(PBRStandardMaterial.SMOOTHNESSSOURCE, 1);
	        }
	        else {
	            this._shaderValues.removeDefine(PBRStandardMaterial.SHADERDEFINE_SMOOTHNESSSOURCE_ALBEDOTEXTURE_ALPHA);
	            this._shaderValues.setInt(PBRStandardMaterial.SMOOTHNESSSOURCE, 0);
	        }
	    }
	    get enableEmission() {
	        return this._shaderValues.getBool(PBRStandardMaterial.ENABLEEMISSION);
	    }
	    set enableEmission(value) {
	        if (value) {
	            this._shaderValues.addDefine(PBRStandardMaterial.SHADERDEFINE_EMISSION);
	        }
	        else {
	            this._shaderValues.removeDefine(PBRStandardMaterial.SHADERDEFINE_EMISSION);
	        }
	        this._shaderValues.setBool(PBRStandardMaterial.ENABLEEMISSION, value);
	    }
	    get emissionColorR() {
	        return this._EmissionColorR;
	    }
	    set emissionColorR(value) {
	        this._EmissionColorR = value;
	    }
	    get emissionColorG() {
	        return this._EmissionColorG;
	    }
	    set emissionColorG(value) {
	        this._EmissionColorG = value;
	    }
	    get emissionColorB() {
	        return this._EmissionColorB;
	    }
	    set emissionColorB(value) {
	        this._EmissionColorB = value;
	    }
	    get emissionColorA() {
	        return this._EmissionColorA;
	    }
	    set emissionColorA(value) {
	        this._EmissionColorA = value;
	    }
	    get emissionColor() {
	        return this._shaderValues.getVector(PBRStandardMaterial.EMISSIONCOLOR);
	    }
	    set emissionColor(value) {
	        this._shaderValues.setVector(PBRStandardMaterial.EMISSIONCOLOR, value);
	    }
	    get emissionTexture() {
	        return this._shaderValues.getTexture(PBRStandardMaterial.EMISSIONTEXTURE);
	    }
	    set emissionTexture(value) {
	        if (value) {
	            this._shaderValues.addDefine(PBRStandardMaterial.SHADERDEFINE_EMISSIONTEXTURE);
	        }
	        else {
	            this._shaderValues.removeDefine(PBRStandardMaterial.SHADERDEFINE_EMISSIONTEXTURE);
	        }
	        this._shaderValues.setTexture(PBRStandardMaterial.EMISSIONTEXTURE, value);
	    }
	    get enableReflection() {
	        return this._shaderValues.getBool(PBRStandardMaterial.ENABLEREFLECT);
	    }
	    set enableReflection(value) {
	        this._shaderValues.setBool(PBRStandardMaterial.ENABLEREFLECT, true);
	        if (value) {
	            this._disablePublicDefineDatas.remove(Scene3DShaderDeclaration.SHADERDEFINE_REFLECTMAP);
	        }
	        else {
	            this._disablePublicDefineDatas.add(Scene3DShaderDeclaration.SHADERDEFINE_REFLECTMAP);
	        }
	    }
	    get tilingOffsetX() {
	        return this._MainTex_STX;
	    }
	    set tilingOffsetX(x) {
	        this._MainTex_STX = x;
	    }
	    get tilingOffsetY() {
	        return this._MainTex_STY;
	    }
	    set tilingOffsetY(y) {
	        this._MainTex_STY = y;
	    }
	    get tilingOffsetZ() {
	        return this._MainTex_STZ;
	    }
	    set tilingOffsetZ(z) {
	        this._MainTex_STZ = z;
	    }
	    get tilingOffsetW() {
	        return this._MainTex_STW;
	    }
	    set tilingOffsetW(w) {
	        this._MainTex_STW = w;
	    }
	    get tilingOffset() {
	        return this._shaderValues.getVector(PBRStandardMaterial.TILINGOFFSET);
	    }
	    set tilingOffset(value) {
	        if (value) {
	            if (value.x != 1 || value.y != 1 || value.z != 0 || value.w != 0) {
	                this._shaderValues.addDefine(PBRStandardMaterial.SHADERDEFINE_TILINGOFFSET);
	            }
	            else {
	                this._shaderValues.removeDefine(PBRStandardMaterial.SHADERDEFINE_TILINGOFFSET);
	            }
	        }
	        else {
	            this._shaderValues.removeDefine(PBRStandardMaterial.SHADERDEFINE_TILINGOFFSET);
	        }
	        this._shaderValues.setVector(PBRStandardMaterial.TILINGOFFSET, value);
	    }
	    set renderMode(value) {
	        switch (value) {
	            case PBRStandardMaterial.RENDERMODE_OPAQUE:
	                this.alphaTest = false;
	                this.renderQueue = BaseMaterial.RENDERQUEUE_OPAQUE;
	                this.depthWrite = true;
	                this.cull = RenderState.CULL_BACK;
	                this.blend = RenderState.BLEND_DISABLE;
	                this.depthTest = RenderState.DEPTHTEST_LESS;
	                this._shaderValues.removeDefine(PBRStandardMaterial.SHADERDEFINE_ALPHAPREMULTIPLY);
	                break;
	            case PBRStandardMaterial.RENDERMODE_CUTOUT:
	                this.renderQueue = BaseMaterial.RENDERQUEUE_ALPHATEST;
	                this.alphaTest = true;
	                this.depthWrite = true;
	                this.cull = RenderState.CULL_BACK;
	                this.blend = RenderState.BLEND_DISABLE;
	                this.depthTest = RenderState.DEPTHTEST_LESS;
	                this._shaderValues.removeDefine(PBRStandardMaterial.SHADERDEFINE_ALPHAPREMULTIPLY);
	                break;
	            case PBRStandardMaterial.RENDERMODE_FADE:
	                this.renderQueue = BaseMaterial.RENDERQUEUE_TRANSPARENT;
	                this.alphaTest = false;
	                this.depthWrite = false;
	                this.cull = RenderState.CULL_BACK;
	                this.blend = RenderState.BLEND_ENABLE_ALL;
	                this.blendSrc = RenderState.BLENDPARAM_SRC_ALPHA;
	                this.blendDst = RenderState.BLENDPARAM_ONE_MINUS_SRC_ALPHA;
	                this.depthTest = RenderState.DEPTHTEST_LESS;
	                this._shaderValues.removeDefine(PBRStandardMaterial.SHADERDEFINE_ALPHAPREMULTIPLY);
	                break;
	                break;
	            case PBRStandardMaterial.RENDERMODE_TRANSPARENT:
	                this.renderQueue = BaseMaterial.RENDERQUEUE_TRANSPARENT;
	                this.alphaTest = false;
	                this.depthWrite = false;
	                this.cull = RenderState.CULL_BACK;
	                this.blend = RenderState.BLEND_ENABLE_ALL;
	                this.blendSrc = RenderState.BLENDPARAM_ONE;
	                this.blendDst = RenderState.BLENDPARAM_ONE_MINUS_SRC_ALPHA;
	                this.depthTest = RenderState.DEPTHTEST_LESS;
	                this._shaderValues.addDefine(PBRStandardMaterial.SHADERDEFINE_ALPHAPREMULTIPLY);
	                break;
	            default:
	                throw new Error("PBRSpecularMaterial : renderMode value error.");
	        }
	    }
	    get depthWrite() {
	        return this._shaderValues.getBool(PBRStandardMaterial.DEPTH_WRITE);
	    }
	    set depthWrite(value) {
	        this._shaderValues.setBool(PBRStandardMaterial.DEPTH_WRITE, value);
	    }
	    get cull() {
	        return this._shaderValues.getInt(PBRStandardMaterial.CULL);
	    }
	    set cull(value) {
	        this._shaderValues.setInt(PBRStandardMaterial.CULL, value);
	    }
	    get blend() {
	        return this._shaderValues.getInt(PBRStandardMaterial.BLEND);
	    }
	    set blend(value) {
	        this._shaderValues.setInt(PBRStandardMaterial.BLEND, value);
	    }
	    get blendSrc() {
	        return this._shaderValues.getInt(PBRStandardMaterial.BLEND_SRC);
	    }
	    set blendSrc(value) {
	        this._shaderValues.setInt(PBRStandardMaterial.BLEND_SRC, value);
	    }
	    get blendDst() {
	        return this._shaderValues.getInt(PBRStandardMaterial.BLEND_DST);
	    }
	    set blendDst(value) {
	        this._shaderValues.setInt(PBRStandardMaterial.BLEND_DST, value);
	    }
	    get depthTest() {
	        return this._shaderValues.getInt(PBRStandardMaterial.DEPTH_TEST);
	    }
	    set depthTest(value) {
	        this._shaderValues.setInt(PBRStandardMaterial.DEPTH_TEST, value);
	    }
	    clone() {
	        var dest = new PBRStandardMaterial();
	        this.cloneTo(dest);
	        return dest;
	    }
	    cloneTo(destObject) {
	        super.cloneTo(destObject);
	        var destMaterial = destObject;
	        this._albedoColor.cloneTo(destMaterial._albedoColor);
	        this._emissionColor.cloneTo(destMaterial._emissionColor);
	    }
	}
	PBRStandardMaterial.SmoothnessSource_MetallicGlossTexture_Alpha = 0;
	PBRStandardMaterial.SmoothnessSource_AlbedoTexture_Alpha = 1;
	PBRStandardMaterial.RENDERMODE_OPAQUE = 0;
	PBRStandardMaterial.RENDERMODE_CUTOUT = 1;
	PBRStandardMaterial.RENDERMODE_FADE = 2;
	PBRStandardMaterial.RENDERMODE_TRANSPARENT = 3;
	PBRStandardMaterial.ALBEDOTEXTURE = Shader3D.propertyNameToID("u_AlbedoTexture");
	PBRStandardMaterial.METALLICGLOSSTEXTURE = Shader3D.propertyNameToID("u_MetallicGlossTexture");
	PBRStandardMaterial.NORMALTEXTURE = Shader3D.propertyNameToID("u_NormalTexture");
	PBRStandardMaterial.PARALLAXTEXTURE = Shader3D.propertyNameToID("u_ParallaxTexture");
	PBRStandardMaterial.OCCLUSIONTEXTURE = Shader3D.propertyNameToID("u_OcclusionTexture");
	PBRStandardMaterial.EMISSIONTEXTURE = Shader3D.propertyNameToID("u_EmissionTexture");
	PBRStandardMaterial.ALBEDOCOLOR = Shader3D.propertyNameToID("u_AlbedoColor");
	PBRStandardMaterial.EMISSIONCOLOR = Shader3D.propertyNameToID("u_EmissionColor");
	PBRStandardMaterial.METALLIC = Shader3D.propertyNameToID("u_metallic");
	PBRStandardMaterial.SMOOTHNESS = Shader3D.propertyNameToID("u_smoothness");
	PBRStandardMaterial.SMOOTHNESSSCALE = Shader3D.propertyNameToID("u_smoothnessScale");
	PBRStandardMaterial.SMOOTHNESSSOURCE = -1;
	PBRStandardMaterial.OCCLUSIONSTRENGTH = Shader3D.propertyNameToID("u_occlusionStrength");
	PBRStandardMaterial.NORMALSCALE = Shader3D.propertyNameToID("u_normalScale");
	PBRStandardMaterial.PARALLAXSCALE = Shader3D.propertyNameToID("u_parallaxScale");
	PBRStandardMaterial.ENABLEEMISSION = -1;
	PBRStandardMaterial.ENABLEREFLECT = -1;
	PBRStandardMaterial.TILINGOFFSET = Shader3D.propertyNameToID("u_TilingOffset");
	PBRStandardMaterial.CULL = Shader3D.propertyNameToID("s_Cull");
	PBRStandardMaterial.BLEND = Shader3D.propertyNameToID("s_Blend");
	PBRStandardMaterial.BLEND_SRC = Shader3D.propertyNameToID("s_BlendSrc");
	PBRStandardMaterial.BLEND_DST = Shader3D.propertyNameToID("s_BlendDst");
	PBRStandardMaterial.DEPTH_TEST = Shader3D.propertyNameToID("s_DepthTest");
	PBRStandardMaterial.DEPTH_WRITE = Shader3D.propertyNameToID("s_DepthWrite");

	class SkyBoxMaterial extends BaseMaterial {
	    constructor() {
	        super();
	        this.setShaderName("SkyBox");
	        this.tintColor = new Vector4(0.5, 0.5, 0.5, 0.5);
	        this.exposure = 1.0;
	        this.rotation = 0;
	    }
	    static __initDefine__() {
	    }
	    get tintColor() {
	        return this._shaderValues.getVector(SkyBoxMaterial.TINTCOLOR);
	    }
	    set tintColor(value) {
	        this._shaderValues.setVector(SkyBoxMaterial.TINTCOLOR, value);
	    }
	    get exposure() {
	        return this._shaderValues.getNumber(SkyBoxMaterial.EXPOSURE);
	    }
	    set exposure(value) {
	        this._shaderValues.setNumber(SkyBoxMaterial.EXPOSURE, value);
	    }
	    get rotation() {
	        return this._shaderValues.getNumber(SkyBoxMaterial.ROTATION);
	    }
	    set rotation(value) {
	        this._shaderValues.setNumber(SkyBoxMaterial.ROTATION, value);
	    }
	    get textureCube() {
	        return this._shaderValues.getTexture(SkyBoxMaterial.TEXTURECUBE);
	    }
	    set textureCube(value) {
	        this._shaderValues.setTexture(SkyBoxMaterial.TEXTURECUBE, value);
	    }
	    clone() {
	        var dest = new SkyBoxMaterial();
	        this.cloneTo(dest);
	        return dest;
	    }
	}
	SkyBoxMaterial.TINTCOLOR = Shader3D.propertyNameToID("u_TintColor");
	SkyBoxMaterial.EXPOSURE = Shader3D.propertyNameToID("u_Exposure");
	SkyBoxMaterial.ROTATION = Shader3D.propertyNameToID("u_Rotation");
	SkyBoxMaterial.TEXTURECUBE = Shader3D.propertyNameToID("u_CubeTexture");

	class SkyProceduralMaterial extends BaseMaterial {
	    constructor() {
	        super();
	        this.setShaderName("SkyBoxProcedural");
	        this.sunDisk = SkyProceduralMaterial.SUN_HIGH_QUALITY;
	        this.sunSize = 0.04;
	        this.sunSizeConvergence = 5;
	        this.atmosphereThickness = 1.0;
	        this.skyTint = new Vector4(0.5, 0.5, 0.5, 1.0);
	        this.groundTint = new Vector4(0.369, 0.349, 0.341, 1.0);
	        this.exposure = 1.3;
	    }
	    static __initDefine__() {
	        SkyProceduralMaterial.SHADERDEFINE_SUN_HIGH_QUALITY = Shader3D.getDefineByName("SUN_HIGH_QUALITY");
	        SkyProceduralMaterial.SHADERDEFINE_SUN_SIMPLE = Shader3D.getDefineByName("SUN_SIMPLE");
	    }
	    get sunDisk() {
	        return this._sunDisk;
	    }
	    set sunDisk(value) {
	        switch (value) {
	            case SkyProceduralMaterial.SUN_HIGH_QUALITY:
	                this._shaderValues.removeDefine(SkyProceduralMaterial.SHADERDEFINE_SUN_SIMPLE);
	                this._shaderValues.addDefine(SkyProceduralMaterial.SHADERDEFINE_SUN_HIGH_QUALITY);
	                break;
	            case SkyProceduralMaterial.SUN_SIMPLE:
	                this._shaderValues.removeDefine(SkyProceduralMaterial.SHADERDEFINE_SUN_HIGH_QUALITY);
	                this._shaderValues.addDefine(SkyProceduralMaterial.SHADERDEFINE_SUN_SIMPLE);
	                break;
	            case SkyProceduralMaterial.SUN_NODE:
	                this._shaderValues.removeDefine(SkyProceduralMaterial.SHADERDEFINE_SUN_HIGH_QUALITY);
	                this._shaderValues.removeDefine(SkyProceduralMaterial.SHADERDEFINE_SUN_SIMPLE);
	                break;
	            default:
	                throw "SkyBoxProceduralMaterial: unknown sun value.";
	        }
	        this._sunDisk = value;
	    }
	    get sunSize() {
	        return this._shaderValues.getNumber(SkyProceduralMaterial.SUNSIZE);
	    }
	    set sunSize(value) {
	        value = Math.min(Math.max(0.0, value), 1.0);
	        this._shaderValues.setNumber(SkyProceduralMaterial.SUNSIZE, value);
	    }
	    get sunSizeConvergence() {
	        return this._shaderValues.getNumber(SkyProceduralMaterial.SUNSIZECONVERGENCE);
	    }
	    set sunSizeConvergence(value) {
	        value = Math.min(Math.max(0.0, value), 20.0);
	        this._shaderValues.setNumber(SkyProceduralMaterial.SUNSIZECONVERGENCE, value);
	    }
	    get atmosphereThickness() {
	        return this._shaderValues.getNumber(SkyProceduralMaterial.ATMOSPHERETHICKNESS);
	    }
	    set atmosphereThickness(value) {
	        value = Math.min(Math.max(0.0, value), 5.0);
	        this._shaderValues.setNumber(SkyProceduralMaterial.ATMOSPHERETHICKNESS, value);
	    }
	    get skyTint() {
	        return this._shaderValues.getVector(SkyProceduralMaterial.SKYTINT);
	    }
	    set skyTint(value) {
	        this._shaderValues.setVector(SkyProceduralMaterial.SKYTINT, value);
	    }
	    get groundTint() {
	        return this._shaderValues.getVector(SkyProceduralMaterial.GROUNDTINT);
	    }
	    set groundTint(value) {
	        this._shaderValues.setVector(SkyProceduralMaterial.GROUNDTINT, value);
	    }
	    get exposure() {
	        return this._shaderValues.getNumber(SkyProceduralMaterial.EXPOSURE);
	    }
	    set exposure(value) {
	        value = Math.min(Math.max(0.0, value), 8.0);
	        this._shaderValues.setNumber(SkyProceduralMaterial.EXPOSURE, value);
	    }
	    clone() {
	        var dest = new SkyProceduralMaterial();
	        this.cloneTo(dest);
	        return dest;
	    }
	}
	SkyProceduralMaterial.SUN_NODE = 0;
	SkyProceduralMaterial.SUN_SIMPLE = 1;
	SkyProceduralMaterial.SUN_HIGH_QUALITY = 2;
	SkyProceduralMaterial.SUNSIZE = Shader3D.propertyNameToID("u_SunSize");
	SkyProceduralMaterial.SUNSIZECONVERGENCE = Shader3D.propertyNameToID("u_SunSizeConvergence");
	SkyProceduralMaterial.ATMOSPHERETHICKNESS = Shader3D.propertyNameToID("u_AtmosphereThickness");
	SkyProceduralMaterial.SKYTINT = Shader3D.propertyNameToID("u_SkyTint");
	SkyProceduralMaterial.GROUNDTINT = Shader3D.propertyNameToID("u_GroundTint");
	SkyProceduralMaterial.EXPOSURE = Shader3D.propertyNameToID("u_Exposure");

	class UnlitMaterial extends BaseMaterial {
	    constructor() {
	        super();
	        this._albedoColor = new Vector4(1.0, 1.0, 1.0, 1.0);
	        this._albedoIntensity = 1.0;
	        this._enableVertexColor = false;
	        this.setShaderName("Unlit");
	        this._shaderValues.setVector(UnlitMaterial.ALBEDOCOLOR, new Vector4(1.0, 1.0, 1.0, 1.0));
	        this.renderMode = UnlitMaterial.RENDERMODE_OPAQUE;
	    }
	    static __initDefine__() {
	        UnlitMaterial.SHADERDEFINE_ALBEDOTEXTURE = Shader3D.getDefineByName("ALBEDOTEXTURE");
	        UnlitMaterial.SHADERDEFINE_TILINGOFFSET = Shader3D.getDefineByName("TILINGOFFSET");
	        UnlitMaterial.SHADERDEFINE_ENABLEVERTEXCOLOR = Shader3D.getDefineByName("ENABLEVERTEXCOLOR");
	    }
	    get _ColorR() {
	        return this._albedoColor.x;
	    }
	    set _ColorR(value) {
	        this._albedoColor.x = value;
	        this.albedoColor = this._albedoColor;
	    }
	    get _ColorG() {
	        return this._albedoColor.y;
	    }
	    set _ColorG(value) {
	        this._albedoColor.y = value;
	        this.albedoColor = this._albedoColor;
	    }
	    get _ColorB() {
	        return this._albedoColor.z;
	    }
	    set _ColorB(value) {
	        this._albedoColor.z = value;
	        this.albedoColor = this._albedoColor;
	    }
	    get _ColorA() {
	        return this._albedoColor.w;
	    }
	    set _ColorA(value) {
	        this._albedoColor.w = value;
	        this.albedoColor = this._albedoColor;
	    }
	    get _AlbedoIntensity() {
	        return this._albedoIntensity;
	    }
	    set _AlbedoIntensity(value) {
	        if (this._albedoIntensity !== value) {
	            var finalAlbedo = this._shaderValues.getVector(UnlitMaterial.ALBEDOCOLOR);
	            Vector4.scale(this._albedoColor, value, finalAlbedo);
	            this._albedoIntensity = value;
	            this._shaderValues.setVector(UnlitMaterial.ALBEDOCOLOR, finalAlbedo);
	        }
	    }
	    get _MainTex_STX() {
	        return this._shaderValues.getVector(UnlitMaterial.TILINGOFFSET).x;
	    }
	    set _MainTex_STX(x) {
	        var tilOff = this._shaderValues.getVector(UnlitMaterial.TILINGOFFSET);
	        tilOff.x = x;
	        this.tilingOffset = tilOff;
	    }
	    get _MainTex_STY() {
	        return this._shaderValues.getVector(UnlitMaterial.TILINGOFFSET).y;
	    }
	    set _MainTex_STY(y) {
	        var tilOff = this._shaderValues.getVector(UnlitMaterial.TILINGOFFSET);
	        tilOff.y = y;
	        this.tilingOffset = tilOff;
	    }
	    get _MainTex_STZ() {
	        return this._shaderValues.getVector(UnlitMaterial.TILINGOFFSET).z;
	    }
	    set _MainTex_STZ(z) {
	        var tilOff = this._shaderValues.getVector(UnlitMaterial.TILINGOFFSET);
	        tilOff.z = z;
	        this.tilingOffset = tilOff;
	    }
	    get _MainTex_STW() {
	        return this._shaderValues.getVector(UnlitMaterial.TILINGOFFSET).w;
	    }
	    set _MainTex_STW(w) {
	        var tilOff = this._shaderValues.getVector(UnlitMaterial.TILINGOFFSET);
	        tilOff.w = w;
	        this.tilingOffset = tilOff;
	    }
	    get _Cutoff() {
	        return this.alphaTestValue;
	    }
	    set _Cutoff(value) {
	        this.alphaTestValue = value;
	    }
	    get albedoColorR() {
	        return this._ColorR;
	    }
	    set albedoColorR(value) {
	        this._ColorR = value;
	    }
	    get albedoColorG() {
	        return this._ColorG;
	    }
	    set albedoColorG(value) {
	        this._ColorG = value;
	    }
	    get albedoColorB() {
	        return this._ColorB;
	    }
	    set albedoColorB(value) {
	        this._ColorB = value;
	    }
	    get albedoColorA() {
	        return this._ColorA;
	    }
	    set albedoColorA(value) {
	        this._ColorA = value;
	    }
	    get albedoColor() {
	        return this._albedoColor;
	    }
	    set albedoColor(value) {
	        var finalAlbedo = this._shaderValues.getVector(UnlitMaterial.ALBEDOCOLOR);
	        Vector4.scale(value, this._albedoIntensity, finalAlbedo);
	        this._albedoColor = value;
	        this._shaderValues.setVector(UnlitMaterial.ALBEDOCOLOR, finalAlbedo);
	    }
	    get albedoIntensity() {
	        return this._albedoIntensity;
	    }
	    set albedoIntensity(value) {
	        this._AlbedoIntensity = value;
	    }
	    get albedoTexture() {
	        return this._shaderValues.getTexture(UnlitMaterial.ALBEDOTEXTURE);
	    }
	    set albedoTexture(value) {
	        if (value)
	            this._shaderValues.addDefine(UnlitMaterial.SHADERDEFINE_ALBEDOTEXTURE);
	        else
	            this._shaderValues.removeDefine(UnlitMaterial.SHADERDEFINE_ALBEDOTEXTURE);
	        this._shaderValues.setTexture(UnlitMaterial.ALBEDOTEXTURE, value);
	    }
	    get tilingOffsetX() {
	        return this._MainTex_STX;
	    }
	    set tilingOffsetX(x) {
	        this._MainTex_STX = x;
	    }
	    get tilingOffsetY() {
	        return this._MainTex_STY;
	    }
	    set tilingOffsetY(y) {
	        this._MainTex_STY = y;
	    }
	    get tilingOffsetZ() {
	        return this._MainTex_STZ;
	    }
	    set tilingOffsetZ(z) {
	        this._MainTex_STZ = z;
	    }
	    get tilingOffsetW() {
	        return this._MainTex_STW;
	    }
	    set tilingOffsetW(w) {
	        this._MainTex_STW = w;
	    }
	    get tilingOffset() {
	        return this._shaderValues.getVector(UnlitMaterial.TILINGOFFSET);
	    }
	    set tilingOffset(value) {
	        if (value) {
	            if (value.x != 1 || value.y != 1 || value.z != 0 || value.w != 0)
	                this._shaderValues.addDefine(UnlitMaterial.SHADERDEFINE_TILINGOFFSET);
	            else
	                this._shaderValues.removeDefine(UnlitMaterial.SHADERDEFINE_TILINGOFFSET);
	        }
	        else {
	            this._shaderValues.removeDefine(UnlitMaterial.SHADERDEFINE_TILINGOFFSET);
	        }
	        this._shaderValues.setVector(UnlitMaterial.TILINGOFFSET, value);
	    }
	    get enableVertexColor() {
	        return this._enableVertexColor;
	    }
	    set enableVertexColor(value) {
	        this._enableVertexColor = value;
	        if (value)
	            this._shaderValues.addDefine(UnlitMaterial.SHADERDEFINE_ENABLEVERTEXCOLOR);
	        else
	            this._shaderValues.removeDefine(UnlitMaterial.SHADERDEFINE_ENABLEVERTEXCOLOR);
	    }
	    set renderMode(value) {
	        switch (value) {
	            case UnlitMaterial.RENDERMODE_OPAQUE:
	                this.alphaTest = false;
	                this.renderQueue = BaseMaterial.RENDERQUEUE_OPAQUE;
	                this.depthWrite = true;
	                this.cull = RenderState.CULL_BACK;
	                this.blend = RenderState.BLEND_DISABLE;
	                this.depthTest = RenderState.DEPTHTEST_LESS;
	                break;
	            case UnlitMaterial.RENDERMODE_CUTOUT:
	                this.renderQueue = BaseMaterial.RENDERQUEUE_ALPHATEST;
	                this.alphaTest = true;
	                this.depthWrite = true;
	                this.cull = RenderState.CULL_BACK;
	                this.blend = RenderState.BLEND_DISABLE;
	                this.depthTest = RenderState.DEPTHTEST_LESS;
	                break;
	            case UnlitMaterial.RENDERMODE_TRANSPARENT:
	                this.renderQueue = BaseMaterial.RENDERQUEUE_TRANSPARENT;
	                this.alphaTest = false;
	                this.depthWrite = false;
	                this.cull = RenderState.CULL_BACK;
	                this.blend = RenderState.BLEND_ENABLE_ALL;
	                this.blendSrc = RenderState.BLENDPARAM_SRC_ALPHA;
	                this.blendDst = RenderState.BLENDPARAM_ONE_MINUS_SRC_ALPHA;
	                this.depthTest = RenderState.DEPTHTEST_LESS;
	                break;
	            default:
	                throw new Error("UnlitMaterial : renderMode value error.");
	        }
	    }
	    get depthWrite() {
	        return this._shaderValues.getBool(UnlitMaterial.DEPTH_WRITE);
	    }
	    set depthWrite(value) {
	        this._shaderValues.setBool(UnlitMaterial.DEPTH_WRITE, value);
	    }
	    get cull() {
	        return this._shaderValues.getInt(UnlitMaterial.CULL);
	    }
	    set cull(value) {
	        this._shaderValues.setInt(UnlitMaterial.CULL, value);
	    }
	    get blend() {
	        return this._shaderValues.getInt(UnlitMaterial.BLEND);
	    }
	    set blend(value) {
	        this._shaderValues.setInt(UnlitMaterial.BLEND, value);
	    }
	    get blendSrc() {
	        return this._shaderValues.getInt(UnlitMaterial.BLEND_SRC);
	    }
	    set blendSrc(value) {
	        this._shaderValues.setInt(UnlitMaterial.BLEND_SRC, value);
	    }
	    get blendDst() {
	        return this._shaderValues.getInt(UnlitMaterial.BLEND_DST);
	    }
	    set blendDst(value) {
	        this._shaderValues.setInt(UnlitMaterial.BLEND_DST, value);
	    }
	    get depthTest() {
	        return this._shaderValues.getInt(UnlitMaterial.DEPTH_TEST);
	    }
	    set depthTest(value) {
	        this._shaderValues.setInt(UnlitMaterial.DEPTH_TEST, value);
	    }
	    clone() {
	        var dest = new UnlitMaterial();
	        this.cloneTo(dest);
	        return dest;
	    }
	}
	UnlitMaterial.RENDERMODE_OPAQUE = 0;
	UnlitMaterial.RENDERMODE_CUTOUT = 1;
	UnlitMaterial.RENDERMODE_TRANSPARENT = 2;
	UnlitMaterial.RENDERMODE_ADDTIVE = 3;
	UnlitMaterial.ALBEDOTEXTURE = Shader3D.propertyNameToID("u_AlbedoTexture");
	UnlitMaterial.ALBEDOCOLOR = Shader3D.propertyNameToID("u_AlbedoColor");
	UnlitMaterial.TILINGOFFSET = Shader3D.propertyNameToID("u_TilingOffset");
	UnlitMaterial.CULL = Shader3D.propertyNameToID("s_Cull");
	UnlitMaterial.BLEND = Shader3D.propertyNameToID("s_Blend");
	UnlitMaterial.BLEND_SRC = Shader3D.propertyNameToID("s_BlendSrc");
	UnlitMaterial.BLEND_DST = Shader3D.propertyNameToID("s_BlendDst");
	UnlitMaterial.DEPTH_TEST = Shader3D.propertyNameToID("s_DepthTest");
	UnlitMaterial.DEPTH_WRITE = Shader3D.propertyNameToID("s_DepthWrite");

	class WaterPrimaryMaterial extends BaseMaterial {
	    constructor() {
	        super();
	        this.setShaderName("WaterPrimary");
	        this._shaderValues.setVector(WaterPrimaryMaterial.HORIZONCOLOR, new Vector4(0.172, 0.463, 0.435, 0));
	        this._shaderValues.setNumber(WaterPrimaryMaterial.WAVESCALE, 0.15);
	        this._shaderValues.setVector(WaterPrimaryMaterial.WAVESPEED, new Vector4(19, 9, -16, -7));
	    }
	    static __initDefine__() {
	        WaterPrimaryMaterial.SHADERDEFINE_MAINTEXTURE = Shader3D.getDefineByName("MAINTEXTURE");
	        WaterPrimaryMaterial.SHADERDEFINE_NORMALTEXTURE = Shader3D.getDefineByName("NORMALTEXTURE");
	    }
	    get horizonColor() {
	        return this._shaderValues.getVector(WaterPrimaryMaterial.HORIZONCOLOR);
	    }
	    set horizonColor(value) {
	        this._shaderValues.setVector(WaterPrimaryMaterial.HORIZONCOLOR, value);
	    }
	    get mainTexture() {
	        return this._shaderValues.getTexture(WaterPrimaryMaterial.MAINTEXTURE);
	    }
	    set mainTexture(value) {
	        if (value)
	            this._shaderValues.addDefine(WaterPrimaryMaterial.SHADERDEFINE_MAINTEXTURE);
	        else
	            this._shaderValues.removeDefine(WaterPrimaryMaterial.SHADERDEFINE_MAINTEXTURE);
	        this._shaderValues.setTexture(WaterPrimaryMaterial.MAINTEXTURE, value);
	    }
	    get normalTexture() {
	        return this._shaderValues.getTexture(WaterPrimaryMaterial.NORMALTEXTURE);
	    }
	    set normalTexture(value) {
	        if (value)
	            this._shaderValues.addDefine(WaterPrimaryMaterial.SHADERDEFINE_NORMALTEXTURE);
	        else
	            this._shaderValues.removeDefine(WaterPrimaryMaterial.SHADERDEFINE_NORMALTEXTURE);
	        this._shaderValues.setTexture(WaterPrimaryMaterial.NORMALTEXTURE, value);
	    }
	    get waveScale() {
	        return this._shaderValues.getNumber(WaterPrimaryMaterial.WAVESCALE);
	    }
	    set waveScale(value) {
	        this._shaderValues.setNumber(WaterPrimaryMaterial.WAVESCALE, value);
	    }
	    get waveSpeed() {
	        return this._shaderValues.getVector(WaterPrimaryMaterial.WAVESPEED);
	    }
	    set waveSpeed(value) {
	        this._shaderValues.setVector(WaterPrimaryMaterial.WAVESPEED, value);
	    }
	    clone() {
	        var dest = new WaterPrimaryMaterial();
	        this.cloneTo(dest);
	        return dest;
	    }
	}
	WaterPrimaryMaterial.HORIZONCOLOR = Shader3D.propertyNameToID("u_HorizonColor");
	WaterPrimaryMaterial.MAINTEXTURE = Shader3D.propertyNameToID("u_MainTexture");
	WaterPrimaryMaterial.NORMALTEXTURE = Shader3D.propertyNameToID("u_NormalTexture");
	WaterPrimaryMaterial.WAVESCALE = Shader3D.propertyNameToID("u_WaveScale");
	WaterPrimaryMaterial.WAVESPEED = Shader3D.propertyNameToID("u_WaveSpeed");

	class Color {
	    constructor(r = 1, g = 1, b = 1, a = 1) {
	        this.r = r;
	        this.g = g;
	        this.b = b;
	        this.a = a;
	    }
	    static gammaToLinearSpace(value) {
	        if (value <= 0.04045)
	            return value / 12.92;
	        else if (value < 1.0)
	            return Math.pow((value + 0.055) / 1.055, 2.4);
	        else
	            return Math.pow(value, 2.4);
	    }
	    static linearToGammaSpace(value) {
	        if (value <= 0.0)
	            return 0.0;
	        else if (value <= 0.0031308)
	            return 12.92 * value;
	        else if (value <= 1.0)
	            return 1.055 * Math.pow(value, 0.41666) - 0.055;
	        else
	            return Math.pow(value, 0.41666);
	    }
	    toLinear(out) {
	        out.r = Color.gammaToLinearSpace(this.r);
	        out.g = Color.gammaToLinearSpace(this.g);
	        out.b = Color.gammaToLinearSpace(this.b);
	    }
	    toGamma(out) {
	        out.r = Color.linearToGammaSpace(this.r);
	        out.g = Color.linearToGammaSpace(this.g);
	        out.b = Color.linearToGammaSpace(this.b);
	    }
	    cloneTo(destObject) {
	        var destColor = destObject;
	        destColor.r = this.r;
	        destColor.g = this.g;
	        destColor.b = this.b;
	        destColor.a = this.a;
	    }
	    clone() {
	        var dest = new Color();
	        this.cloneTo(dest);
	        return dest;
	    }
	    forNativeElement() {
	    }
	}
	Color.RED = new Color(1, 0, 0, 1);
	Color.GREEN = new Color(0, 1, 0, 1);
	Color.BLUE = new Color(0, 0, 1, 1);
	Color.CYAN = new Color(0, 1, 1, 1);
	Color.YELLOW = new Color(1, 0.92, 0.016, 1);
	Color.MAGENTA = new Color(1, 0, 1, 1);
	Color.GRAY = new Color(0.5, 0.5, 0.5, 1);
	Color.WHITE = new Color(1, 1, 1, 1);
	Color.BLACK = new Color(0, 0, 0, 1);

	class DynamicBatchManager {
	    constructor() {
	        this._batchRenderElementPool = [];
	    }
	    static _registerManager(manager) {
	        DynamicBatchManager._managers.push(manager);
	    }
	    _clear() {
	        this._batchRenderElementPoolIndex = 0;
	    }
	    _getBatchRenderElementFromPool() {
	        throw "StaticBatch:must override this function.";
	    }
	    dispose() {
	    }
	}
	DynamicBatchManager._managers = [];

	class Transform3D extends Laya.EventDispatcher {
	    constructor(owner) {
	        super();
	        this._localPosition = new Vector3(0, 0, 0);
	        this._localRotation = new Quaternion(0, 0, 0, 1);
	        this._localScale = new Vector3(1, 1, 1);
	        this._localRotationEuler = new Vector3(0, 0, 0);
	        this._localMatrix = new Matrix4x4();
	        this._position = new Vector3(0, 0, 0);
	        this._rotation = new Quaternion(0, 0, 0, 1);
	        this._scale = new Vector3(1, 1, 1);
	        this._rotationEuler = new Vector3(0, 0, 0);
	        this._worldMatrix = new Matrix4x4();
	        this._children = null;
	        this._parent = null;
	        this._dummy = null;
	        this._transformFlag = 0;
	        this._owner = owner;
	        this._children = [];
	        this._setTransformFlag(Transform3D.TRANSFORM_LOCALQUATERNION | Transform3D.TRANSFORM_LOCALEULER | Transform3D.TRANSFORM_LOCALMATRIX, false);
	        this._setTransformFlag(Transform3D.TRANSFORM_WORLDPOSITION | Transform3D.TRANSFORM_WORLDQUATERNION | Transform3D.TRANSFORM_WORLDEULER | Transform3D.TRANSFORM_WORLDSCALE | Transform3D.TRANSFORM_WORLDMATRIX, true);
	    }
	    get _isFrontFaceInvert() {
	        var scale = this.getWorldLossyScale();
	        var isInvert = scale.x < 0;
	        (scale.y < 0) && (isInvert = !isInvert);
	        (scale.z < 0) && (isInvert = !isInvert);
	        return isInvert;
	    }
	    get owner() {
	        return this._owner;
	    }
	    get worldNeedUpdate() {
	        return this._getTransformFlag(Transform3D.TRANSFORM_WORLDMATRIX);
	    }
	    get localPositionX() {
	        return this._localPosition.x;
	    }
	    set localPositionX(x) {
	        this._localPosition.x = x;
	        this.localPosition = this._localPosition;
	    }
	    get localPositionY() {
	        return this._localPosition.y;
	    }
	    set localPositionY(y) {
	        this._localPosition.y = y;
	        this.localPosition = this._localPosition;
	    }
	    get localPositionZ() {
	        return this._localPosition.z;
	    }
	    set localPositionZ(z) {
	        this._localPosition.z = z;
	        this.localPosition = this._localPosition;
	    }
	    get localPosition() {
	        return this._localPosition;
	    }
	    set localPosition(value) {
	        if (this._localPosition !== value)
	            value.cloneTo(this._localPosition);
	        this._setTransformFlag(Transform3D.TRANSFORM_LOCALMATRIX, true);
	        this._onWorldPositionTransform();
	    }
	    get localRotationX() {
	        return this.localRotation.x;
	    }
	    set localRotationX(x) {
	        this._localRotation.x = x;
	        this.localRotation = this._localRotation;
	    }
	    get localRotationY() {
	        return this.localRotation.y;
	    }
	    set localRotationY(y) {
	        this._localRotation.y = y;
	        this.localRotation = this._localRotation;
	    }
	    get localRotationZ() {
	        return this.localRotation.z;
	    }
	    set localRotationZ(z) {
	        this._localRotation.z = z;
	        this.localRotation = this._localRotation;
	    }
	    get localRotationW() {
	        return this.localRotation.w;
	    }
	    set localRotationW(w) {
	        this._localRotation.w = w;
	        this.localRotation = this._localRotation;
	    }
	    get localRotation() {
	        if (this._getTransformFlag(Transform3D.TRANSFORM_LOCALQUATERNION)) {
	            var eulerE = this._localRotationEuler;
	            Quaternion.createFromYawPitchRoll(eulerE.y / Transform3D._angleToRandin, eulerE.x / Transform3D._angleToRandin, eulerE.z / Transform3D._angleToRandin, this._localRotation);
	            this._setTransformFlag(Transform3D.TRANSFORM_LOCALQUATERNION, false);
	        }
	        return this._localRotation;
	    }
	    set localRotation(value) {
	        if (this._localRotation !== value)
	            value.cloneTo(this._localRotation);
	        this._localRotation.normalize(this._localRotation);
	        this._setTransformFlag(Transform3D.TRANSFORM_LOCALEULER | Transform3D.TRANSFORM_LOCALMATRIX, true);
	        this._setTransformFlag(Transform3D.TRANSFORM_LOCALQUATERNION, false);
	        this._onWorldRotationTransform();
	    }
	    get localScaleX() {
	        return this._localScale.x;
	    }
	    set localScaleX(value) {
	        this._localScale.x = value;
	        this.localScale = this._localScale;
	    }
	    get localScaleY() {
	        return this._localScale.y;
	    }
	    set localScaleY(value) {
	        this._localScale.y = value;
	        this.localScale = this._localScale;
	    }
	    get localScaleZ() {
	        return this._localScale.z;
	    }
	    set localScaleZ(value) {
	        this._localScale.z = value;
	        this.localScale = this._localScale;
	    }
	    get localScale() {
	        return this._localScale;
	    }
	    set localScale(value) {
	        if (this._localScale !== value)
	            value.cloneTo(this._localScale);
	        this._setTransformFlag(Transform3D.TRANSFORM_LOCALMATRIX, true);
	        this._onWorldScaleTransform();
	    }
	    get localRotationEulerX() {
	        return this.localRotationEuler.x;
	    }
	    set localRotationEulerX(value) {
	        this._localRotationEuler.x = value;
	        this.localRotationEuler = this._localRotationEuler;
	    }
	    get localRotationEulerY() {
	        return this.localRotationEuler.y;
	    }
	    set localRotationEulerY(value) {
	        this._localRotationEuler.y = value;
	        this.localRotationEuler = this._localRotationEuler;
	    }
	    get localRotationEulerZ() {
	        return this.localRotationEuler.z;
	    }
	    set localRotationEulerZ(value) {
	        this._localRotationEuler.z = value;
	        this.localRotationEuler = this._localRotationEuler;
	    }
	    get localRotationEuler() {
	        if (this._getTransformFlag(Transform3D.TRANSFORM_LOCALEULER)) {
	            this._localRotation.getYawPitchRoll(Transform3D._tempVector30);
	            var euler = Transform3D._tempVector30;
	            var localRotationEuler = this._localRotationEuler;
	            localRotationEuler.x = euler.y * Transform3D._angleToRandin;
	            localRotationEuler.y = euler.x * Transform3D._angleToRandin;
	            localRotationEuler.z = euler.z * Transform3D._angleToRandin;
	            this._setTransformFlag(Transform3D.TRANSFORM_LOCALEULER, false);
	        }
	        return this._localRotationEuler;
	    }
	    set localRotationEuler(value) {
	        if (this._localRotationEuler !== value)
	            value.cloneTo(this._localRotationEuler);
	        this._setTransformFlag(Transform3D.TRANSFORM_LOCALEULER, false);
	        this._setTransformFlag(Transform3D.TRANSFORM_LOCALQUATERNION | Transform3D.TRANSFORM_LOCALMATRIX, true);
	        this._onWorldRotationTransform();
	    }
	    get localMatrix() {
	        if (this._getTransformFlag(Transform3D.TRANSFORM_LOCALMATRIX)) {
	            Matrix4x4.createAffineTransformation(this._localPosition, this.localRotation, this._localScale, this._localMatrix);
	            this._setTransformFlag(Transform3D.TRANSFORM_LOCALMATRIX, false);
	        }
	        return this._localMatrix;
	    }
	    set localMatrix(value) {
	        if (this._localMatrix !== value)
	            value.cloneTo(this._localMatrix);
	        this._localMatrix.decomposeTransRotScale(this._localPosition, this._localRotation, this._localScale);
	        this._setTransformFlag(Transform3D.TRANSFORM_LOCALEULER, true);
	        this._setTransformFlag(Transform3D.TRANSFORM_LOCALMATRIX, false);
	        this._onWorldTransform();
	    }
	    get position() {
	        if (this._getTransformFlag(Transform3D.TRANSFORM_WORLDPOSITION)) {
	            if (this._parent != null) {
	                var worldMatE = this.worldMatrix.elements;
	                this._position.x = worldMatE[12];
	                this._position.y = worldMatE[13];
	                this._position.z = worldMatE[14];
	            }
	            else {
	                this._localPosition.cloneTo(this._position);
	            }
	            this._setTransformFlag(Transform3D.TRANSFORM_WORLDPOSITION, false);
	        }
	        return this._position;
	    }
	    set position(value) {
	        if (this._parent != null) {
	            var parentInvMat = Transform3D._tempMatrix0;
	            this._parent.worldMatrix.invert(parentInvMat);
	            Vector3.transformCoordinate(value, parentInvMat, this._localPosition);
	        }
	        else {
	            value.cloneTo(this._localPosition);
	        }
	        this.localPosition = this._localPosition;
	        if (this._position !== value)
	            value.cloneTo(this._position);
	        this._setTransformFlag(Transform3D.TRANSFORM_WORLDPOSITION, false);
	    }
	    get rotation() {
	        if (this._getTransformFlag(Transform3D.TRANSFORM_WORLDQUATERNION)) {
	            if (this._parent != null)
	                Quaternion.multiply(this._parent.rotation, this.localRotation, this._rotation);
	            else
	                this.localRotation.cloneTo(this._rotation);
	            this._setTransformFlag(Transform3D.TRANSFORM_WORLDQUATERNION, false);
	        }
	        return this._rotation;
	    }
	    set rotation(value) {
	        if (this._parent != null) {
	            this._parent.rotation.invert(Transform3D._tempQuaternion0);
	            Quaternion.multiply(Transform3D._tempQuaternion0, value, this._localRotation);
	        }
	        else {
	            value.cloneTo(this._localRotation);
	        }
	        this.localRotation = this._localRotation;
	        if (value !== this._rotation)
	            value.cloneTo(this._rotation);
	        this._setTransformFlag(Transform3D.TRANSFORM_WORLDQUATERNION, false);
	    }
	    get rotationEuler() {
	        if (this._getTransformFlag(Transform3D.TRANSFORM_WORLDEULER)) {
	            this.rotation.getYawPitchRoll(Transform3D._tempVector30);
	            var eulerE = Transform3D._tempVector30;
	            var rotationEulerE = this._rotationEuler;
	            rotationEulerE.x = eulerE.y * Transform3D._angleToRandin;
	            rotationEulerE.y = eulerE.x * Transform3D._angleToRandin;
	            rotationEulerE.z = eulerE.z * Transform3D._angleToRandin;
	            this._setTransformFlag(Transform3D.TRANSFORM_WORLDEULER, false);
	        }
	        return this._rotationEuler;
	    }
	    set rotationEuler(value) {
	        Quaternion.createFromYawPitchRoll(value.y / Transform3D._angleToRandin, value.x / Transform3D._angleToRandin, value.z / Transform3D._angleToRandin, this._rotation);
	        this.rotation = this._rotation;
	        if (this._rotationEuler !== value)
	            value.cloneTo(this._rotationEuler);
	        this._setTransformFlag(Transform3D.TRANSFORM_WORLDEULER, false);
	    }
	    get worldMatrix() {
	        if (this._getTransformFlag(Transform3D.TRANSFORM_WORLDMATRIX)) {
	            if (this._parent != null)
	                Matrix4x4.multiply(this._parent.worldMatrix, this.localMatrix, this._worldMatrix);
	            else
	                this.localMatrix.cloneTo(this._worldMatrix);
	            this._setTransformFlag(Transform3D.TRANSFORM_WORLDMATRIX, false);
	        }
	        return this._worldMatrix;
	    }
	    set worldMatrix(value) {
	        if (this._parent === null) {
	            value.cloneTo(this._localMatrix);
	        }
	        else {
	            this._parent.worldMatrix.invert(this._localMatrix);
	            Matrix4x4.multiply(this._localMatrix, value, this._localMatrix);
	        }
	        this.localMatrix = this._localMatrix;
	        if (this._worldMatrix !== value)
	            value.cloneTo(this._worldMatrix);
	        this._setTransformFlag(Transform3D.TRANSFORM_WORLDMATRIX, false);
	    }
	    _getScaleMatrix() {
	        var invRotation = Transform3D._tempQuaternion0;
	        var invRotationMat = Transform3D._tempMatrix3x30;
	        var worldRotScaMat = Transform3D._tempMatrix3x31;
	        var scaMat = Transform3D._tempMatrix3x32;
	        Matrix3x3.createFromMatrix4x4(this.worldMatrix, worldRotScaMat);
	        this.rotation.invert(invRotation);
	        Matrix3x3.createRotationQuaternion(invRotation, invRotationMat);
	        Matrix3x3.multiply(invRotationMat, worldRotScaMat, scaMat);
	        return scaMat;
	    }
	    _setTransformFlag(type, value) {
	        if (value)
	            this._transformFlag |= type;
	        else
	            this._transformFlag &= ~type;
	    }
	    _getTransformFlag(type) {
	        return (this._transformFlag & type) != 0;
	    }
	    _setParent(value) {
	        if (this._parent !== value) {
	            if (this._parent) {
	                var parentChilds = this._parent._children;
	                var index = parentChilds.indexOf(this);
	                parentChilds.splice(index, 1);
	            }
	            if (value) {
	                value._children.push(this);
	                (value) && (this._onWorldTransform());
	            }
	            this._parent = value;
	        }
	    }
	    _onWorldPositionRotationTransform() {
	        if (!this._getTransformFlag(Transform3D.TRANSFORM_WORLDMATRIX) || !this._getTransformFlag(Transform3D.TRANSFORM_WORLDPOSITION) || !this._getTransformFlag(Transform3D.TRANSFORM_WORLDQUATERNION) || !this._getTransformFlag(Transform3D.TRANSFORM_WORLDEULER)) {
	            this._setTransformFlag(Transform3D.TRANSFORM_WORLDMATRIX | Transform3D.TRANSFORM_WORLDPOSITION | Transform3D.TRANSFORM_WORLDQUATERNION | Transform3D.TRANSFORM_WORLDEULER, true);
	            this.event(Laya.Event.TRANSFORM_CHANGED, this._transformFlag);
	            for (var i = 0, n = this._children.length; i < n; i++)
	                this._children[i]._onWorldPositionRotationTransform();
	        }
	    }
	    _onWorldPositionScaleTransform() {
	        if (!this._getTransformFlag(Transform3D.TRANSFORM_WORLDMATRIX) || !this._getTransformFlag(Transform3D.TRANSFORM_WORLDPOSITION) || !this._getTransformFlag(Transform3D.TRANSFORM_WORLDSCALE)) {
	            this._setTransformFlag(Transform3D.TRANSFORM_WORLDMATRIX | Transform3D.TRANSFORM_WORLDPOSITION | Transform3D.TRANSFORM_WORLDSCALE, true);
	            this.event(Laya.Event.TRANSFORM_CHANGED, this._transformFlag);
	            for (var i = 0, n = this._children.length; i < n; i++)
	                this._children[i]._onWorldPositionScaleTransform();
	        }
	    }
	    _onWorldPositionTransform() {
	        if (!this._getTransformFlag(Transform3D.TRANSFORM_WORLDMATRIX) || !this._getTransformFlag(Transform3D.TRANSFORM_WORLDPOSITION)) {
	            this._setTransformFlag(Transform3D.TRANSFORM_WORLDMATRIX | Transform3D.TRANSFORM_WORLDPOSITION, true);
	            this.event(Laya.Event.TRANSFORM_CHANGED, this._transformFlag);
	            for (var i = 0, n = this._children.length; i < n; i++)
	                this._children[i]._onWorldPositionTransform();
	        }
	    }
	    _onWorldRotationTransform() {
	        if (!this._getTransformFlag(Transform3D.TRANSFORM_WORLDMATRIX) || !this._getTransformFlag(Transform3D.TRANSFORM_WORLDQUATERNION) || !this._getTransformFlag(Transform3D.TRANSFORM_WORLDEULER)) {
	            this._setTransformFlag(Transform3D.TRANSFORM_WORLDMATRIX | Transform3D.TRANSFORM_WORLDQUATERNION | Transform3D.TRANSFORM_WORLDEULER, true);
	            this.event(Laya.Event.TRANSFORM_CHANGED, this._transformFlag);
	            for (var i = 0, n = this._children.length; i < n; i++)
	                this._children[i]._onWorldPositionRotationTransform();
	        }
	    }
	    _onWorldScaleTransform() {
	        if (!this._getTransformFlag(Transform3D.TRANSFORM_WORLDMATRIX) || !this._getTransformFlag(Transform3D.TRANSFORM_WORLDSCALE)) {
	            this._setTransformFlag(Transform3D.TRANSFORM_WORLDMATRIX | Transform3D.TRANSFORM_WORLDSCALE, true);
	            this.event(Laya.Event.TRANSFORM_CHANGED, this._transformFlag);
	            for (var i = 0, n = this._children.length; i < n; i++)
	                this._children[i]._onWorldPositionScaleTransform();
	        }
	    }
	    _onWorldTransform() {
	        if (!this._getTransformFlag(Transform3D.TRANSFORM_WORLDMATRIX) || !this._getTransformFlag(Transform3D.TRANSFORM_WORLDPOSITION) || !this._getTransformFlag(Transform3D.TRANSFORM_WORLDQUATERNION) || !this._getTransformFlag(Transform3D.TRANSFORM_WORLDEULER) || !this._getTransformFlag(Transform3D.TRANSFORM_WORLDSCALE)) {
	            this._setTransformFlag(Transform3D.TRANSFORM_WORLDMATRIX | Transform3D.TRANSFORM_WORLDPOSITION | Transform3D.TRANSFORM_WORLDQUATERNION | Transform3D.TRANSFORM_WORLDEULER | Transform3D.TRANSFORM_WORLDSCALE, true);
	            this.event(Laya.Event.TRANSFORM_CHANGED, this._transformFlag);
	            for (var i = 0, n = this._children.length; i < n; i++)
	                this._children[i]._onWorldTransform();
	        }
	    }
	    translate(translation, isLocal = true) {
	        if (isLocal) {
	            Matrix4x4.createFromQuaternion(this.localRotation, Transform3D._tempMatrix0);
	            Vector3.transformCoordinate(translation, Transform3D._tempMatrix0, Transform3D._tempVector30);
	            Vector3.add(this.localPosition, Transform3D._tempVector30, this._localPosition);
	            this.localPosition = this._localPosition;
	        }
	        else {
	            Vector3.add(this.position, translation, this._position);
	            this.position = this._position;
	        }
	    }
	    rotate(rotation, isLocal = true, isRadian = true) {
	        var rot;
	        if (isRadian) {
	            rot = rotation;
	        }
	        else {
	            Vector3.scale(rotation, Math.PI / 180.0, Transform3D._tempVector30);
	            rot = Transform3D._tempVector30;
	        }
	        Quaternion.createFromYawPitchRoll(rot.y, rot.x, rot.z, Transform3D._tempQuaternion0);
	        if (isLocal) {
	            Quaternion.multiply(this._localRotation, Transform3D._tempQuaternion0, this._localRotation);
	            this.localRotation = this._localRotation;
	        }
	        else {
	            Quaternion.multiply(Transform3D._tempQuaternion0, this.rotation, this._rotation);
	            this.rotation = this._rotation;
	        }
	    }
	    getForward(forward) {
	        var worldMatElem = this.worldMatrix.elements;
	        forward.x = -worldMatElem[8];
	        forward.y = -worldMatElem[9];
	        forward.z = -worldMatElem[10];
	    }
	    getUp(up) {
	        var worldMatElem = this.worldMatrix.elements;
	        up.x = worldMatElem[4];
	        up.y = worldMatElem[5];
	        up.z = worldMatElem[6];
	    }
	    getRight(right) {
	        var worldMatElem = this.worldMatrix.elements;
	        right.x = worldMatElem[0];
	        right.y = worldMatElem[1];
	        right.z = worldMatElem[2];
	    }
	    lookAt(target, up, isLocal = false) {
	        var eye;
	        if (isLocal) {
	            eye = this._localPosition;
	            if (Math.abs(eye.x - target.x) < MathUtils3D.zeroTolerance && Math.abs(eye.y - target.y) < MathUtils3D.zeroTolerance && Math.abs(eye.z - target.z) < MathUtils3D.zeroTolerance)
	                return;
	            Quaternion.lookAt(this._localPosition, target, up, this._localRotation);
	            this._localRotation.invert(this._localRotation);
	            this.localRotation = this._localRotation;
	        }
	        else {
	            var worldPosition = this.position;
	            eye = worldPosition;
	            if (Math.abs(eye.x - target.x) < MathUtils3D.zeroTolerance && Math.abs(eye.y - target.y) < MathUtils3D.zeroTolerance && Math.abs(eye.z - target.z) < MathUtils3D.zeroTolerance)
	                return;
	            Quaternion.lookAt(worldPosition, target, up, this._rotation);
	            this._rotation.invert(this._rotation);
	            this.rotation = this._rotation;
	        }
	    }
	    getWorldLossyScale() {
	        if (this._getTransformFlag(Transform3D.TRANSFORM_WORLDSCALE)) {
	            if (this._parent !== null) {
	                var scaMatE = this._getScaleMatrix().elements;
	                this._scale.x = scaMatE[0];
	                this._scale.y = scaMatE[4];
	                this._scale.z = scaMatE[8];
	            }
	            else {
	                this._localScale.cloneTo(this._scale);
	            }
	            this._setTransformFlag(Transform3D.TRANSFORM_WORLDSCALE, false);
	        }
	        return this._scale;
	    }
	    setWorldLossyScale(value) {
	        if (this._parent !== null) {
	            var scaleMat = Transform3D._tempMatrix3x33;
	            var localScaleMat = Transform3D._tempMatrix3x33;
	            var localScaleMatE = localScaleMat.elements;
	            var parInvScaleMat = this._parent._getScaleMatrix();
	            parInvScaleMat.invert(parInvScaleMat);
	            Matrix3x3.createFromScaling(value, scaleMat);
	            Matrix3x3.multiply(parInvScaleMat, scaleMat, localScaleMat);
	            this._localScale.x = localScaleMatE[0];
	            this._localScale.y = localScaleMatE[4];
	            this._localScale.z = localScaleMatE[8];
	        }
	        else {
	            value.cloneTo(this._localScale);
	        }
	        this.localScale = this._localScale;
	        if (this._scale !== value)
	            value.cloneTo(this._scale);
	        this._setTransformFlag(Transform3D.TRANSFORM_WORLDSCALE, false);
	    }
	    get scale() {
	        console.warn("Transfrm3D: discard function,please use getWorldLossyScale instead.");
	        return this.getWorldLossyScale();
	    }
	    set scale(value) {
	        console.warn("Transfrm3D: discard function,please use setWorldLossyScale instead.");
	        this.setWorldLossyScale(value);
	    }
	}
	Transform3D._tempVector30 = new Vector3();
	Transform3D._tempQuaternion0 = new Quaternion();
	Transform3D._tempMatrix0 = new Matrix4x4();
	Transform3D._tempMatrix3x30 = new Matrix3x3();
	Transform3D._tempMatrix3x31 = new Matrix3x3();
	Transform3D._tempMatrix3x32 = new Matrix3x3();
	Transform3D._tempMatrix3x33 = new Matrix3x3();
	Transform3D.TRANSFORM_LOCALQUATERNION = 0x01;
	Transform3D.TRANSFORM_LOCALEULER = 0x02;
	Transform3D.TRANSFORM_LOCALMATRIX = 0x04;
	Transform3D.TRANSFORM_WORLDPOSITION = 0x08;
	Transform3D.TRANSFORM_WORLDQUATERNION = 0x10;
	Transform3D.TRANSFORM_WORLDSCALE = 0x20;
	Transform3D.TRANSFORM_WORLDMATRIX = 0x40;
	Transform3D.TRANSFORM_WORLDEULER = 0x80;
	Transform3D._angleToRandin = 180 / Math.PI;

	class Sprite3D extends Laya.Node {
	    constructor(name = null, isStatic = false) {
	        super();
	        this._needProcessCollisions = false;
	        this._needProcessTriggers = false;
	        this._id = ++Sprite3D._uniqueIDCounter;
	        this._transform = new Transform3D(this);
	        this._isStatic = isStatic;
	        this.layer = 0;
	        this.name = name ? name : "New Sprite3D";
	    }
	    static __init__() {
	    }
	    static instantiate(original, parent = null, worldPositionStays = true, position = null, rotation = null) {
	        var destSprite3D = original.clone();
	        (parent) && (parent.addChild(destSprite3D));
	        var transform = destSprite3D.transform;
	        if (worldPositionStays) {
	            var worldMatrix = transform.worldMatrix;
	            original.transform.worldMatrix.cloneTo(worldMatrix);
	            transform.worldMatrix = worldMatrix;
	        }
	        else {
	            (position) && (transform.position = position);
	            (rotation) && (transform.rotation = rotation);
	        }
	        return destSprite3D;
	    }
	    static load(url, complete) {
	        Laya.Laya.loader.create(url, complete, null, Sprite3D.HIERARCHY);
	    }
	    get id() {
	        return this._id;
	    }
	    get layer() {
	        return this._layer;
	    }
	    set layer(value) {
	        if (this._layer !== value) {
	            if (value >= 0 && value <= 30) {
	                this._layer = value;
	            }
	            else {
	                throw new Error("Layer value must be 0-30.");
	            }
	        }
	    }
	    get url() {
	        return this._url;
	    }
	    get isStatic() {
	        return this._isStatic;
	    }
	    get transform() {
	        return this._transform;
	    }
	    _setCreateURL(url) {
	        this._url = Laya.URL.formatURL(url);
	    }
	    _changeAnimatorsToLinkSprite3D(sprite3D, isLink, path) {
	        var animator = this.getComponent(Animator);
	        if (animator) {
	            if (!animator.avatar)
	                sprite3D._changeAnimatorToLinkSprite3DNoAvatar(animator, isLink, path);
	        }
	        if (this._parent && this._parent instanceof Sprite3D) {
	            path.unshift(this._parent.name);
	            var p = this._parent;
	            (p._hierarchyAnimator) && (p._changeAnimatorsToLinkSprite3D(sprite3D, isLink, path));
	        }
	    }
	    _setHierarchyAnimator(animator, parentAnimator) {
	        this._changeHierarchyAnimator(animator);
	        this._changeAnimatorAvatar(animator.avatar);
	        for (var i = 0, n = this._children.length; i < n; i++) {
	            var child = this._children[i];
	            (child._hierarchyAnimator == parentAnimator) && (child._setHierarchyAnimator(animator, parentAnimator));
	        }
	    }
	    _clearHierarchyAnimator(animator, parentAnimator) {
	        this._changeHierarchyAnimator(parentAnimator);
	        this._changeAnimatorAvatar(parentAnimator ? parentAnimator.avatar : null);
	        for (var i = 0, n = this._children.length; i < n; i++) {
	            var child = this._children[i];
	            (child._hierarchyAnimator == animator) && (child._clearHierarchyAnimator(animator, parentAnimator));
	        }
	    }
	    _changeHierarchyAnimatorAvatar(animator, avatar) {
	        this._changeAnimatorAvatar(avatar);
	        for (var i = 0, n = this._children.length; i < n; i++) {
	            var child = this._children[i];
	            (child._hierarchyAnimator == animator) && (child._changeHierarchyAnimatorAvatar(animator, avatar));
	        }
	    }
	    _changeAnimatorToLinkSprite3DNoAvatar(animator, isLink, path) {
	        animator._handleSpriteOwnersBySprite(isLink, path, this);
	        for (var i = 0, n = this._children.length; i < n; i++) {
	            var child = this._children[i];
	            var index = path.length;
	            path.push(child.name);
	            child._changeAnimatorToLinkSprite3DNoAvatar(animator, isLink, path);
	            path.splice(index, 1);
	        }
	    }
	    _changeHierarchyAnimator(animator) {
	        this._hierarchyAnimator = animator;
	    }
	    _changeAnimatorAvatar(avatar) {
	    }
	    _onAdded() {
	        if (this._parent instanceof Sprite3D) {
	            var parent3D = this._parent;
	            this.transform._setParent(parent3D.transform);
	            if (parent3D._hierarchyAnimator) {
	                (!this._hierarchyAnimator) && (this._setHierarchyAnimator(parent3D._hierarchyAnimator, null));
	                parent3D._changeAnimatorsToLinkSprite3D(this, true, [this.name]);
	            }
	        }
	        super._onAdded();
	    }
	    _onRemoved() {
	        super._onRemoved();
	        if (this._parent instanceof Sprite3D) {
	            var parent3D = this._parent;
	            this.transform._setParent(null);
	            if (parent3D._hierarchyAnimator) {
	                (this._hierarchyAnimator == parent3D._hierarchyAnimator) && (this._clearHierarchyAnimator(parent3D._hierarchyAnimator, null));
	                parent3D._changeAnimatorsToLinkSprite3D(this, false, [this.name]);
	            }
	        }
	    }
	    _parse(data, spriteMap) {
	        (data.isStatic !== undefined) && (this._isStatic = data.isStatic);
	        (data.active !== undefined) && (this.active = data.active);
	        (data.name != undefined) && (this.name = data.name);
	        if (data.position !== undefined) {
	            var loccalPosition = this.transform.localPosition;
	            loccalPosition.fromArray(data.position);
	            this.transform.localPosition = loccalPosition;
	        }
	        if (data.rotationEuler !== undefined) {
	            var localRotationEuler = this.transform.localRotationEuler;
	            localRotationEuler.fromArray(data.rotationEuler);
	            this.transform.localRotationEuler = localRotationEuler;
	        }
	        if (data.rotation !== undefined) {
	            var localRotation = this.transform.localRotation;
	            localRotation.fromArray(data.rotation);
	            this.transform.localRotation = localRotation;
	        }
	        if (data.scale !== undefined) {
	            var localScale = this.transform.localScale;
	            localScale.fromArray(data.scale);
	            this.transform.localScale = localScale;
	        }
	        (data.layer != undefined) && (this.layer = data.layer);
	    }
	    _cloneTo(destObject, srcRoot, dstRoot) {
	        if (this.destroyed)
	            throw new Error("Sprite3D: Can't be cloned if the Sprite3D has destroyed.");
	        var destSprite3D = destObject;
	        destSprite3D.name = this.name;
	        destSprite3D.destroyed = this.destroyed;
	        destSprite3D.active = this.active;
	        var destLocalPosition = destSprite3D.transform.localPosition;
	        this.transform.localPosition.cloneTo(destLocalPosition);
	        destSprite3D.transform.localPosition = destLocalPosition;
	        var destLocalRotation = destSprite3D.transform.localRotation;
	        this.transform.localRotation.cloneTo(destLocalRotation);
	        destSprite3D.transform.localRotation = destLocalRotation;
	        var destLocalScale = destSprite3D.transform.localScale;
	        this.transform.localScale.cloneTo(destLocalScale);
	        destSprite3D.transform.localScale = destLocalScale;
	        destSprite3D._isStatic = this._isStatic;
	        destSprite3D.layer = this.layer;
	        super._cloneTo(destSprite3D, srcRoot, dstRoot);
	    }
	    static _createSprite3DInstance(scrSprite) {
	        var node = scrSprite._create();
	        var children = scrSprite._children;
	        for (var i = 0, n = children.length; i < n; i++) {
	            var child = Sprite3D._createSprite3DInstance(children[i]);
	            node.addChild(child);
	        }
	        return node;
	    }
	    static _parseSprite3DInstance(srcRoot, dstRoot, scrSprite, dstSprite) {
	        var srcChildren = scrSprite._children;
	        var dstChildren = dstSprite._children;
	        for (var i = 0, n = srcChildren.length; i < n; i++)
	            Sprite3D._parseSprite3DInstance(srcRoot, dstRoot, srcChildren[i], dstChildren[i]);
	        scrSprite._cloneTo(dstSprite, srcRoot, dstRoot);
	    }
	    clone() {
	        var dstSprite3D = Sprite3D._createSprite3DInstance(this);
	        Sprite3D._parseSprite3DInstance(this, dstSprite3D, this, dstSprite3D);
	        return dstSprite3D;
	    }
	    destroy(destroyChild = true) {
	        if (this.destroyed)
	            return;
	        super.destroy(destroyChild);
	        this._transform = null;
	        this._scripts = null;
	        this._url && Laya.Loader.clearRes(this._url);
	    }
	    _create() {
	        return new Sprite3D();
	    }
	}
	Sprite3D.HIERARCHY = "HIERARCHY";
	Sprite3D.WORLDMATRIX = Shader3D.propertyNameToID("u_WorldMat");
	Sprite3D.MVPMATRIX = Shader3D.propertyNameToID("u_MvpMatrix");
	Sprite3D._uniqueIDCounter = 0;

	class RenderableSprite3D extends Sprite3D {
	    constructor(name) {
	        super(name);
	    }
	    static __init__() {
	        RenderableSprite3D.SHADERDEFINE_RECEIVE_SHADOW = Shader3D.getDefineByName("RECEIVESHADOW");
	        RenderableSprite3D.SHADERDEFINE_SCALEOFFSETLIGHTINGMAPUV = Shader3D.getDefineByName("SCALEOFFSETLIGHTINGMAPUV");
	        RenderableSprite3D.SAHDERDEFINE_LIGHTMAP = Shader3D.getDefineByName("LIGHTMAP");
	    }
	    _onInActive() {
	        super._onInActive();
	        var scene3D = this._scene;
	        scene3D._removeRenderObject(this._render);
	        (this._render.castShadow) && (scene3D._removeShadowCastRenderObject(this._render));
	    }
	    _onActive() {
	        super._onActive();
	        var scene3D = this._scene;
	        scene3D._addRenderObject(this._render);
	        (this._render.castShadow) && (scene3D._addShadowCastRenderObject(this._render));
	    }
	    _onActiveInScene() {
	        super._onActiveInScene();
	        if (ILaya3D.Laya3D._editerEnvironment) {
	            var scene = this._scene;
	            var pickColor = new Vector4();
	            scene._allotPickColorByID(this.id, pickColor);
	            scene._pickIdToSprite[this.id] = this;
	            this._render._shaderValues.setVector(RenderableSprite3D.PICKCOLOR, pickColor);
	        }
	    }
	    _addToInitStaticBatchManager() {
	    }
	    _setBelongScene(scene) {
	        super._setBelongScene(scene);
	        this._render._setBelongScene(scene);
	    }
	    _setUnBelongScene() {
	        this._render._shaderValues.removeDefine(RenderableSprite3D.SAHDERDEFINE_LIGHTMAP);
	        super._setUnBelongScene();
	    }
	    _changeHierarchyAnimator(animator) {
	        if (this._hierarchyAnimator) {
	            var renderableSprites = this._hierarchyAnimator._renderableSprites;
	            renderableSprites.splice(renderableSprites.indexOf(this), 1);
	        }
	        if (animator)
	            animator._renderableSprites.push(this);
	        super._changeHierarchyAnimator(animator);
	    }
	    destroy(destroyChild = true) {
	        super.destroy(destroyChild);
	        this._render._destroy();
	        this._render = null;
	    }
	    _create() {
	        return new RenderableSprite3D(this.name);
	    }
	}
	RenderableSprite3D.LIGHTMAPSCALEOFFSET = Shader3D.propertyNameToID("u_LightmapScaleOffset");
	RenderableSprite3D.LIGHTMAP = Shader3D.propertyNameToID("u_LightMap");
	RenderableSprite3D.PICKCOLOR = Shader3D.propertyNameToID("u_PickColor");

	class StaticBatchManager {
	    constructor() {
	        this._initBatchSprites = [];
	        this._staticBatches = {};
	        this._batchRenderElementPoolIndex = 0;
	        this._batchRenderElementPool = [];
	    }
	    static _addToStaticBatchQueue(sprite3D, renderableSprite3D) {
	        if (sprite3D instanceof RenderableSprite3D)
	            renderableSprite3D.push(sprite3D);
	        for (var i = 0, n = sprite3D.numChildren; i < n; i++)
	            StaticBatchManager._addToStaticBatchQueue(sprite3D._children[i], renderableSprite3D);
	    }
	    static _registerManager(manager) {
	        StaticBatchManager._managers.push(manager);
	    }
	    static combine(staticBatchRoot, renderableSprite3Ds = null) {
	        if (!renderableSprite3Ds) {
	            renderableSprite3Ds = [];
	            if (staticBatchRoot)
	                StaticBatchManager._addToStaticBatchQueue(staticBatchRoot, renderableSprite3Ds);
	        }
	        var batchSpritesCount = renderableSprite3Ds.length;
	        if (batchSpritesCount > 0) {
	            for (var i = 0; i < batchSpritesCount; i++) {
	                var sprite = renderableSprite3Ds[i];
	                if (!sprite.destroyed) {
	                    if (sprite._render._isPartOfStaticBatch)
	                        console.warn("StaticBatchManager: Sprite " + sprite.name + " has a part of Static Batch,it will be ignore.");
	                    else
	                        sprite._addToInitStaticBatchManager();
	                }
	            }
	            for (var k = 0, m = StaticBatchManager._managers.length; k < m; k++) {
	                var manager = StaticBatchManager._managers[k];
	                manager._initStaticBatchs(staticBatchRoot);
	            }
	        }
	    }
	    _partition(items, left, right) {
	        var pivot = items[Math.floor((right + left) / 2)];
	        while (left <= right) {
	            while (this._compare(items[left], pivot) < 0)
	                left++;
	            while (this._compare(items[right], pivot) > 0)
	                right--;
	            if (left < right) {
	                var temp = items[left];
	                items[left] = items[right];
	                items[right] = temp;
	                left++;
	                right--;
	            }
	            else if (left === right) {
	                left++;
	                break;
	            }
	        }
	        return left;
	    }
	    _quickSort(items, left, right) {
	        if (items.length > 1) {
	            var index = this._partition(items, left, right);
	            var leftIndex = index - 1;
	            if (left < leftIndex)
	                this._quickSort(items, left, leftIndex);
	            if (index < right)
	                this._quickSort(items, index, right);
	        }
	    }
	    _compare(left, right) {
	        throw "StaticBatch:must override this function.";
	    }
	    _initStaticBatchs(rootSprite) {
	        throw "StaticBatch:must override this function.";
	    }
	    _getBatchRenderElementFromPool() {
	        throw "StaticBatch:must override this function.";
	    }
	    _addBatchSprite(renderableSprite3D) {
	        this._initBatchSprites.push(renderableSprite3D);
	    }
	    _clear() {
	        this._batchRenderElementPoolIndex = 0;
	    }
	    _garbageCollection() {
	        throw "StaticBatchManager: must override it.";
	    }
	    dispose() {
	        this._staticBatches = null;
	    }
	}
	StaticBatchManager._managers = [];

	class FrustumCulling {
	    constructor() {
	    }
	    static __init__() {
	        if (Laya.Render.supportWebGLPlusCulling) {
	            FrustumCulling._cullingBufferLength = 0;
	            FrustumCulling._cullingBuffer = new Float32Array(4096);
	        }
	    }
	    static _drawTraversalCullingBound(renderList, debugTool) {
	        var validCount = renderList.length;
	        var renders = renderList.elements;
	        for (var i = 0, n = renderList.length; i < n; i++) {
	            var color = FrustumCulling._tempColor0;
	            color.r = 0;
	            color.g = 1;
	            color.b = 0;
	            color.a = 1;
	            Utils3D._drawBound(debugTool, renders[i].bounds._getBoundBox(), color);
	        }
	    }
	    static _traversalCulling(camera, scene, context, renderList, customShader, replacementTag) {
	        var validCount = renderList.length;
	        var renders = renderList.elements;
	        var boundFrustum = camera.boundFrustum;
	        var camPos = camera._transform.position;
	        for (var i = 0; i < validCount; i++) {
	            var render = renders[i];
	            if (camera._isLayerVisible(render._owner._layer) && render._enable) {
	                Laya.Stat.frustumCulling++;
	                if (!camera.useOcclusionCulling || render._needRender(boundFrustum, context)) {
	                    render._visible = true;
	                    render._distanceForSort = Vector3.distance(render.bounds.getCenter(), camPos);
	                    var elements = render._renderElements;
	                    for (var j = 0, m = elements.length; j < m; j++)
	                        elements[j]._update(scene, context, customShader, replacementTag);
	                }
	                else {
	                    render._visible = false;
	                }
	            }
	            else {
	                render._visible = false;
	            }
	        }
	    }
	    static renderObjectCulling(camera, scene, context, renderList, customShader, replacementTag) {
	        var i, n;
	        var opaqueQueue = scene._opaqueQueue;
	        var transparentQueue = scene._transparentQueue;
	        opaqueQueue.clear();
	        transparentQueue.clear();
	        var staticBatchManagers = StaticBatchManager._managers;
	        for (i = 0, n = staticBatchManagers.length; i < n; i++)
	            staticBatchManagers[i]._clear();
	        var dynamicBatchManagers = DynamicBatchManager._managers;
	        for (i = 0, n = dynamicBatchManagers.length; i < n; i++)
	            dynamicBatchManagers[i]._clear();
	        var octree = scene._octree;
	        if (octree) {
	            octree.updateMotionObjects();
	            octree.shrinkRootIfPossible();
	            octree.getCollidingWithFrustum(context, customShader, replacementTag);
	        }
	        FrustumCulling._traversalCulling(camera, scene, context, renderList, customShader, replacementTag);
	        if (FrustumCulling.debugFrustumCulling) {
	            var debugTool = scene._debugTool;
	            debugTool.clear();
	            if (octree) {
	                octree.drawAllBounds(debugTool);
	                octree.drawAllObjects(debugTool);
	            }
	            FrustumCulling._drawTraversalCullingBound(renderList, debugTool);
	        }
	        var count = opaqueQueue.elements.length;
	        (count > 0) && (opaqueQueue._quickSort(0, count - 1));
	        count = transparentQueue.elements.length;
	        (count > 0) && (transparentQueue._quickSort(0, count - 1));
	    }
	    static renderObjectCullingNative(camera, scene, context, renderList, customShader, replacementTag) {
	        var i, n, j, m;
	        var opaqueQueue = scene._opaqueQueue;
	        var transparentQueue = scene._transparentQueue;
	        opaqueQueue.clear();
	        transparentQueue.clear();
	        var staticBatchManagers = StaticBatchManager._managers;
	        for (i = 0, n = staticBatchManagers.length; i < n; i++)
	            staticBatchManagers[i]._clear();
	        var dynamicBatchManagers = DynamicBatchManager._managers;
	        for (i = 0, n = dynamicBatchManagers.length; i < n; i++)
	            dynamicBatchManagers[i]._clear();
	        var validCount = renderList.length;
	        var renders = renderList.elements;
	        for (i = 0; i < validCount; i++) {
	            renders[i].bounds;
	            renders[i]._updateForNative && renders[i]._updateForNative(context);
	        }
	        var boundFrustum = camera.boundFrustum;
	        FrustumCulling.cullingNative(camera._boundFrustumBuffer, FrustumCulling._cullingBuffer, scene._cullingBufferIndices, validCount, scene._cullingBufferResult);
	        var camPos = context.camera._transform.position;
	        for (i = 0; i < validCount; i++) {
	            var render = renders[i];
	            if (!camera.useOcclusionCulling || (camera._isLayerVisible(render._owner._layer) && render._enable && scene._cullingBufferResult[i])) {
	                render._visible = true;
	                render._distanceForSort = Vector3.distance(render.bounds.getCenter(), camPos);
	                var elements = render._renderElements;
	                for (j = 0, m = elements.length; j < m; j++) {
	                    var element = elements[j];
	                    element._update(scene, context, customShader, replacementTag);
	                }
	            }
	            else {
	                render._visible = false;
	            }
	        }
	        var count = opaqueQueue.elements.length;
	        (count > 0) && (opaqueQueue._quickSort(0, count - 1));
	        count = transparentQueue.elements.length;
	        (count > 0) && (transparentQueue._quickSort(0, count - 1));
	    }
	    static cullingNative(boundFrustumBuffer, cullingBuffer, cullingBufferIndices, cullingCount, cullingBufferResult) {
	        return Laya.LayaGL.instance.culling(boundFrustumBuffer, cullingBuffer, cullingBufferIndices, cullingCount, cullingBufferResult);
	    }
	}
	FrustumCulling._tempVector3 = new Vector3();
	FrustumCulling._tempColor0 = new Color();
	FrustumCulling.debugFrustumCulling = false;

	class BatchMark {
	    constructor() {
	        this.updateMark = -1;
	        this.indexInList = -1;
	        this.batched = false;
	    }
	}

	class GeometryElement {
	    constructor() {
	        this._destroyed = false;
	    }
	    get destroyed() {
	        return this._destroyed;
	    }
	    _getType() {
	        throw "GeometryElement:must override it.";
	    }
	    _prepareRender(state) {
	        return true;
	    }
	    _render(state) {
	        throw "GeometryElement:must override it.";
	    }
	    destroy() {
	        if (this._destroyed)
	            return;
	        this._destroyed = true;
	    }
	}
	GeometryElement._typeCounter = 0;

	class VertexBuffer3D extends Laya.Buffer {
	    constructor(byteLength, bufferUsage, canRead = false) {
	        super();
	        this._vertexDeclaration = null;
	        this._float32Reader = null;
	        var gl = Laya.LayaGL.instance;
	        this._bufferUsage = bufferUsage;
	        this._bufferType = gl.ARRAY_BUFFER;
	        this._canRead = canRead;
	        this._byteLength = byteLength;
	        this.bind();
	        gl.bufferData(this._bufferType, this._byteLength, this._bufferUsage);
	        if (canRead) {
	            this._buffer = new Uint8Array(byteLength);
	            this._float32Reader = new Float32Array(this._buffer.buffer);
	        }
	    }
	    get vertexDeclaration() {
	        return this._vertexDeclaration;
	    }
	    set vertexDeclaration(value) {
	        this._vertexDeclaration = value;
	    }
	    get canRead() {
	        return this._canRead;
	    }
	    bind() {
	        if (Laya.Buffer._bindedVertexBuffer !== this._glBuffer) {
	            var gl = Laya.LayaGL.instance;
	            gl.bindBuffer(gl.ARRAY_BUFFER, this._glBuffer);
	            Laya.Buffer._bindedVertexBuffer = this._glBuffer;
	            return true;
	        }
	        else {
	            return false;
	        }
	    }
	    setData(buffer, bufferOffset = 0, dataStartIndex = 0, dataCount = Number.MAX_SAFE_INTEGER) {
	        this.bind();
	        var needSubData = dataStartIndex !== 0 || dataCount !== Number.MAX_SAFE_INTEGER;
	        if (needSubData) {
	            var subData = new Uint8Array(buffer, dataStartIndex, dataCount);
	            Laya.LayaGL.instance.bufferSubData(this._bufferType, bufferOffset, subData);
	            if (this._canRead)
	                this._buffer.set(subData, bufferOffset);
	        }
	        else {
	            Laya.LayaGL.instance.bufferSubData(this._bufferType, bufferOffset, buffer);
	            if (this._canRead)
	                this._buffer.set(new Uint8Array(buffer), bufferOffset);
	        }
	    }
	    getUint8Data() {
	        if (this._canRead)
	            return this._buffer;
	        else
	            throw new Error("Can't read data from VertexBuffer with only write flag!");
	    }
	    getFloat32Data() {
	        if (this._canRead)
	            return this._float32Reader;
	        else
	            throw new Error("Can't read data from VertexBuffer with only write flag!");
	    }
	    markAsUnreadbale() {
	        this._canRead = false;
	        this._buffer = null;
	        this._float32Reader = null;
	    }
	    destroy() {
	        super.destroy();
	        this._buffer = null;
	        this._float32Reader = null;
	        this._vertexDeclaration = null;
	    }
	}
	VertexBuffer3D.DATATYPE_FLOAT32ARRAY = 0;
	VertexBuffer3D.DATATYPE_UINT8ARRAY = 1;

	class VertexElementFormat {
	    static __init__() {
	        var gl = Laya.LayaGL.instance;
	        VertexElementFormat._elementInfos = {
	            "single": [1, gl.FLOAT, 0],
	            "vector2": [2, gl.FLOAT, 0],
	            "vector3": [3, gl.FLOAT, 0],
	            "vector4": [4, gl.FLOAT, 0],
	            "color": [4, gl.FLOAT, 0],
	            "byte4": [4, gl.UNSIGNED_BYTE, 0],
	            "short2": [2, gl.FLOAT, 0],
	            "short4": [4, gl.FLOAT, 0],
	            "normalizedshort2": [2, gl.FLOAT, 0],
	            "normalizedshort4": [4, gl.FLOAT, 0],
	            "halfvector2": [2, gl.FLOAT, 0],
	            "halfvector4": [4, gl.FLOAT, 0]
	        };
	    }
	    static getElementInfos(element) {
	        var info = VertexElementFormat._elementInfos[element];
	        if (info)
	            return info;
	        else
	            throw "VertexElementFormat: this vertexElementFormat is not implement.";
	    }
	}
	VertexElementFormat.Single = "single";
	VertexElementFormat.Vector2 = "vector2";
	VertexElementFormat.Vector3 = "vector3";
	VertexElementFormat.Vector4 = "vector4";
	VertexElementFormat.Color = "color";
	VertexElementFormat.Byte4 = "byte4";
	VertexElementFormat.Short2 = "short2";
	VertexElementFormat.Short4 = "short4";
	VertexElementFormat.NormalizedShort2 = "normalizedshort2";
	VertexElementFormat.NormalizedShort4 = "normalizedshort4";
	VertexElementFormat.HalfVector2 = "halfvector2";
	VertexElementFormat.HalfVector4 = "halfvector4";

	class VertexDeclaration {
	    constructor(vertexStride, vertexElements) {
	        this._id = ++VertexDeclaration._uniqueIDCounter;
	        this._vertexElementsDic = {};
	        this._vertexStride = vertexStride;
	        this._vertexElements = vertexElements;
	        var count = vertexElements.length;
	        this._shaderValues = new ShaderData(null);
	        for (var j = 0; j < count; j++) {
	            var vertexElement = vertexElements[j];
	            var name = vertexElement._elementUsage;
	            this._vertexElementsDic[name] = vertexElement;
	            var value = new Int32Array(5);
	            var elmentInfo = VertexElementFormat.getElementInfos(vertexElement._elementFormat);
	            value[0] = elmentInfo[0];
	            value[1] = elmentInfo[1];
	            value[2] = elmentInfo[2];
	            value[3] = this._vertexStride;
	            value[4] = vertexElement._offset;
	            this._shaderValues.setAttribute(name, value);
	        }
	    }
	    get id() {
	        return this._id;
	    }
	    get vertexStride() {
	        return this._vertexStride;
	    }
	    get vertexElementCount() {
	        return this._vertexElements.length;
	    }
	    getVertexElementByIndex(index) {
	        return this._vertexElements[index];
	    }
	    getVertexElementByUsage(usage) {
	        return this._vertexElementsDic[usage];
	    }
	}
	VertexDeclaration._uniqueIDCounter = 1;

	class VertexElement {
	    get offset() {
	        return this._offset;
	    }
	    get elementFormat() {
	        return this._elementFormat;
	    }
	    get elementUsage() {
	        return this._elementUsage;
	    }
	    constructor(offset, elementFormat, elementUsage) {
	        this._offset = offset;
	        this._elementFormat = elementFormat;
	        this._elementUsage = elementUsage;
	    }
	}

	class VertexMesh {
	    static __init__() {
	        VertexMesh.instanceWorldMatrixDeclaration = new VertexDeclaration(64, [new VertexElement(0, VertexElementFormat.Vector4, VertexMesh.MESH_WORLDMATRIX_ROW0),
	            new VertexElement(16, VertexElementFormat.Vector4, VertexMesh.MESH_WORLDMATRIX_ROW1),
	            new VertexElement(32, VertexElementFormat.Vector4, VertexMesh.MESH_WORLDMATRIX_ROW2),
	            new VertexElement(48, VertexElementFormat.Vector4, VertexMesh.MESH_WORLDMATRIX_ROW3)]);
	        VertexMesh.instanceMVPMatrixDeclaration = new VertexDeclaration(64, [new VertexElement(0, VertexElementFormat.Vector4, VertexMesh.MESH_MVPMATRIX_ROW0),
	            new VertexElement(16, VertexElementFormat.Vector4, VertexMesh.MESH_MVPMATRIX_ROW1),
	            new VertexElement(32, VertexElementFormat.Vector4, VertexMesh.MESH_MVPMATRIX_ROW2),
	            new VertexElement(48, VertexElementFormat.Vector4, VertexMesh.MESH_MVPMATRIX_ROW3)]);
	    }
	    static getVertexDeclaration(vertexFlag, compatible = true) {
	        var verDec = VertexMesh._vertexDeclarationMap[vertexFlag + (compatible ? "_0" : "_1")];
	        if (!verDec) {
	            var subFlags = vertexFlag.split(",");
	            var offset = 0;
	            var elements = [];
	            for (var i = 0, n = subFlags.length; i < n; i++) {
	                var element;
	                switch (subFlags[i]) {
	                    case "POSITION":
	                        element = new VertexElement(offset, VertexElementFormat.Vector3, VertexMesh.MESH_POSITION0);
	                        offset += 12;
	                        break;
	                    case "NORMAL":
	                        element = new VertexElement(offset, VertexElementFormat.Vector3, VertexMesh.MESH_NORMAL0);
	                        offset += 12;
	                        break;
	                    case "COLOR":
	                        element = new VertexElement(offset, VertexElementFormat.Vector4, VertexMesh.MESH_COLOR0);
	                        offset += 16;
	                        break;
	                    case "UV":
	                        element = new VertexElement(offset, VertexElementFormat.Vector2, VertexMesh.MESH_TEXTURECOORDINATE0);
	                        offset += 8;
	                        break;
	                    case "UV1":
	                        element = new VertexElement(offset, VertexElementFormat.Vector2, VertexMesh.MESH_TEXTURECOORDINATE1);
	                        offset += 8;
	                        break;
	                    case "BLENDWEIGHT":
	                        element = new VertexElement(offset, VertexElementFormat.Vector4, VertexMesh.MESH_BLENDWEIGHT0);
	                        offset += 16;
	                        break;
	                    case "BLENDINDICES":
	                        if (compatible) {
	                            element = new VertexElement(offset, VertexElementFormat.Vector4, VertexMesh.MESH_BLENDINDICES0);
	                            offset += 16;
	                        }
	                        else {
	                            element = new VertexElement(offset, VertexElementFormat.Byte4, VertexMesh.MESH_BLENDINDICES0);
	                            offset += 4;
	                        }
	                        break;
	                    case "TANGENT":
	                        element = new VertexElement(offset, VertexElementFormat.Vector4, VertexMesh.MESH_TANGENT0);
	                        offset += 16;
	                        break;
	                    default:
	                        throw "VertexMesh: unknown vertex flag.";
	                }
	                elements.push(element);
	            }
	            verDec = new VertexDeclaration(offset, elements);
	            VertexMesh._vertexDeclarationMap[vertexFlag + (compatible ? "_0" : "_1")] = verDec;
	        }
	        return verDec;
	    }
	}
	VertexMesh.MESH_POSITION0 = 0;
	VertexMesh.MESH_COLOR0 = 1;
	VertexMesh.MESH_TEXTURECOORDINATE0 = 2;
	VertexMesh.MESH_NORMAL0 = 3;
	VertexMesh.MESH_TANGENT0 = 4;
	VertexMesh.MESH_BLENDINDICES0 = 5;
	VertexMesh.MESH_BLENDWEIGHT0 = 6;
	VertexMesh.MESH_TEXTURECOORDINATE1 = 7;
	VertexMesh.MESH_WORLDMATRIX_ROW0 = 8;
	VertexMesh.MESH_WORLDMATRIX_ROW1 = 9;
	VertexMesh.MESH_WORLDMATRIX_ROW2 = 10;
	VertexMesh.MESH_WORLDMATRIX_ROW3 = 11;
	VertexMesh.MESH_MVPMATRIX_ROW0 = 12;
	VertexMesh.MESH_MVPMATRIX_ROW1 = 13;
	VertexMesh.MESH_MVPMATRIX_ROW2 = 14;
	VertexMesh.MESH_MVPMATRIX_ROW3 = 15;
	VertexMesh._vertexDeclarationMap = {};

	class SubMeshInstanceBatch extends GeometryElement {
	    constructor() {
	        super();
	        this.maxInstanceCount = 1024;
	        this.instanceWorldMatrixData = new Float32Array(this.maxInstanceCount * 16);
	        this.instanceMVPMatrixData = new Float32Array(this.maxInstanceCount * 16);
	        var gl = Laya.LayaGL.instance;
	        this.instanceWorldMatrixBuffer = new VertexBuffer3D(this.instanceWorldMatrixData.length * 4, gl.DYNAMIC_DRAW);
	        this.instanceMVPMatrixBuffer = new VertexBuffer3D(this.instanceMVPMatrixData.length * 4, gl.DYNAMIC_DRAW);
	        this.instanceWorldMatrixBuffer.vertexDeclaration = VertexMesh.instanceWorldMatrixDeclaration;
	        this.instanceMVPMatrixBuffer.vertexDeclaration = VertexMesh.instanceMVPMatrixDeclaration;
	    }
	    static __init__() {
	        SubMeshInstanceBatch.instance = new SubMeshInstanceBatch();
	    }
	    _render(state) {
	        var gl = Laya.LayaGL.instance;
	        var element = state.renderElement;
	        var subMesh = element.instanceSubMesh;
	        var count = element.instanceBatchElementList.length;
	        var indexCount = subMesh._indexCount;
	        subMesh._mesh._instanceBufferState.bind();
	        Laya.LayaGL.layaGPUInstance.drawElementsInstanced(gl.TRIANGLES, indexCount, gl.UNSIGNED_SHORT, subMesh._indexStart * 2, count);
	        Laya.Stat.renderBatches++;
	        Laya.Stat.savedRenderBatches += count - 1;
	        Laya.Stat.trianglesFaces += indexCount * count / 3;
	    }
	}

	class LightBound {
	}
	class ClusterData {
	    constructor() {
	        this.updateMark = -1;
	        this.pointLightCount = 0;
	        this.spotLightCount = 0;
	        this.indices = [];
	    }
	}
	class Cluster {
	    constructor(xSlices, ySlices, zSlices, maxLightsPerClusterAverage) {
	        this._updateMark = 0;
	        this._depthSliceParam = new Vector2();
	        this._xSlices = xSlices;
	        this._ySlices = ySlices;
	        this._zSlices = zSlices;
	        var clusterTexWidth = xSlices * ySlices;
	        var clisterTexHeight = zSlices * (1 + Math.ceil(maxLightsPerClusterAverage / 4));
	        this._clusterTexture = Utils3D._createFloatTextureBuffer(clusterTexWidth, clisterTexHeight);
	        this._clusterTexture.lock = true;
	        this._clusterPixels = new Float32Array(clusterTexWidth * clisterTexHeight * 4);
	        var clusterDatas = new Array(this._zSlices);
	        for (var z = 0; z < this._zSlices; z++) {
	            clusterDatas[z] = new Array(this._ySlices);
	            for (var y = 0; y < this._ySlices; y++) {
	                clusterDatas[z][y] = new Array(this._xSlices);
	                for (var x = 0; x < this._xSlices; x++)
	                    clusterDatas[z][y][x] = new ClusterData();
	            }
	        }
	        this._clusterDatas = clusterDatas;
	    }
	    _insertSpotLightSphere(origin, forward, size, angle, testSphere) {
	        var V = Cluster._tempVector35;
	        V.x = testSphere.x - origin.x;
	        V.y = testSphere.y - origin.y;
	        V.z = testSphere.z - origin.z;
	        var VlenSq = Vector3.dot(V, V);
	        var sphereRadius = testSphere.w;
	        var rangeCull = VlenSq > sphereRadius * sphereRadius;
	        if (!rangeCull)
	            return false;
	        var V1len = Vector3.dot(V, forward);
	        var distanceClosestPoint = Math.cos(angle) * Math.sqrt(VlenSq - V1len * V1len) - V1len * Math.sin(angle);
	        var angleCull = distanceClosestPoint > sphereRadius;
	        var frontCull = V1len > sphereRadius + size;
	        var backCull = V1len < -sphereRadius;
	        return !(angleCull || frontCull || backCull);
	    }
	    _placePointLightToClusters(lightIndex, lightBound) {
	        var clusterDatas = this._clusterDatas;
	        var updateMark = this._updateMark;
	        for (var z = lightBound.zMin, zEnd = lightBound.zMax; z < zEnd; z++) {
	            for (var y = lightBound.yMin, yEnd = lightBound.yMax; y < yEnd; y++) {
	                for (var x = lightBound.xMin, xEnd = lightBound.xMax; x < xEnd; x++) {
	                    var data = clusterDatas[z][y][x];
	                    if (data.updateMark != updateMark) {
	                        data.pointLightCount = 0;
	                        data.spotLightCount = 0;
	                        data.updateMark = updateMark;
	                    }
	                    var indices = data.indices;
	                    var lightCount = data.pointLightCount++;
	                    if (lightCount < indices.length)
	                        indices[lightCount] = lightIndex;
	                    else
	                        indices.push(lightIndex);
	                }
	            }
	        }
	    }
	    _placeSpotLightToClusters(lightIndex, lightBound) {
	        var clusterDatas = this._clusterDatas;
	        var updateMark = this._updateMark;
	        for (var z = lightBound.zMin, zEnd = lightBound.zMax; z < zEnd; z++) {
	            for (var y = lightBound.yMin, yEnd = lightBound.yMax; y < yEnd; y++) {
	                for (var x = lightBound.xMin, xEnd = lightBound.xMax; x < xEnd; x++) {
	                    var data = clusterDatas[z][y][x];
	                    if (data.updateMark != updateMark) {
	                        data.pointLightCount = 0;
	                        data.spotLightCount = 0;
	                        data.updateMark = updateMark;
	                    }
	                    var indices = data.indices;
	                    var lightCount = data.pointLightCount + data.spotLightCount++;
	                    if (lightCount < indices.length)
	                        indices[lightCount] = lightIndex;
	                    else
	                        indices.push(lightIndex);
	                }
	            }
	        }
	    }
	    _insertConePlane(origin, forward, radius, halfAngle, pNor) {
	        var V1 = Cluster._tempVector36;
	        var V2 = Cluster._tempVector37;
	        Vector3.cross(pNor, forward, V1);
	        Vector3.cross(V1, forward, V2);
	        Vector3.normalize(V2, V2);
	        var tanR = radius * Math.tan(halfAngle);
	        var capRimX = origin.x + radius * forward.x + tanR * V2.x;
	        var capRimY = origin.y + radius * forward.y + tanR * V2.y;
	        var capRimZ = origin.z + radius * forward.z + tanR * V2.z;
	        return capRimX * pNor.x + capRimY * pNor.y + capRimZ * pNor.z <= 0 || origin.x * pNor.x + origin.y * pNor.y + origin.z * pNor.z <= 0;
	    }
	    _shrinkSphereLightZPerspective(near, far, lightviewPos, radius, lightBound) {
	        var lvZ = lightviewPos.z;
	        var minZ = lvZ - radius;
	        var maxZ = lvZ + radius;
	        if ((minZ > far) || (maxZ <= near))
	            return false;
	        var depthSliceParam = this._depthSliceParam;
	        lightBound.zMin = Math.floor(Math.log2(Math.max(minZ, near)) * depthSliceParam.x - depthSliceParam.y);
	        lightBound.zMax = Math.min(Math.ceil(Math.log2(maxZ) * depthSliceParam.x - depthSliceParam.y), this._zSlices);
	        return true;
	    }
	    _shrinkSpotLightZPerspective(near, far, viewLightPos, viewConeCap, radius, halfAngle, lightBound) {
	        var pbX = viewConeCap.x, pbY = viewConeCap.y, pbZ = viewConeCap.z;
	        var rb = Math.tan(halfAngle) * radius;
	        var paX = viewLightPos.x, paY = viewLightPos.y, paZ = viewLightPos.z;
	        var aX = pbX - paX, aY = pbY - paY, aZ = pbZ - paZ;
	        var dotA = aX * aX + aY * aY + aZ * aZ;
	        var eZ = Math.sqrt(1.0 - aZ * aZ / dotA);
	        var minZ = Math.max(Math.min(paZ, pbZ - eZ * rb), viewLightPos.z - radius);
	        var maxZ = Math.min(Math.max(paZ, pbZ + eZ * rb), viewLightPos.z + radius);
	        if ((minZ > far) || (maxZ <= near))
	            return false;
	        var depthSliceParam = this._depthSliceParam;
	        lightBound.zMin = Math.floor(Math.log2(Math.max(minZ, near)) * depthSliceParam.x - depthSliceParam.y);
	        lightBound.zMax = Math.min(Math.ceil(Math.log2(maxZ) * depthSliceParam.x - depthSliceParam.y), this._zSlices);
	        return true;
	    }
	    _shrinkSphereLightByBoundOrth(halfX, halfY, near, far, lightviewPos, radius, lightBound) {
	        var lvZ = lightviewPos.z;
	        var minZ = lvZ - radius, maxZ = lvZ + radius;
	        if ((minZ > far) || (maxZ <= near))
	            return false;
	        var lvX = lightviewPos.x;
	        var minX = lvX - radius, maxX = lvX + radius;
	        if ((minX > halfX) || (maxX <= -halfX))
	            return false;
	        var lvY = lightviewPos.y;
	        var minY = lvY - radius, maxY = lvY + radius;
	        if ((minY > halfY) || (maxY <= -halfY))
	            return false;
	        var xSlices = this._xSlices, ySlices = this._ySlices;
	        var depthSliceParam = this._depthSliceParam;
	        var xStride = halfX * 2 / xSlices, yStride = halfY * 2 / ySlices;
	        lightBound.xMin = Math.max(Math.floor((minX + halfX) / xStride), 0);
	        lightBound.xMax = Math.min(Math.ceil((maxX + halfX) / xStride), xSlices);
	        lightBound.yMin = Math.max(Math.floor((halfY - maxY) / yStride), 0);
	        lightBound.yMax = Math.min(Math.ceil((halfY - minY) / yStride), ySlices);
	        lightBound.zMin = Math.floor(Math.log2(Math.max(minZ, near)) * depthSliceParam.x - depthSliceParam.y);
	        lightBound.zMax = Math.min(Math.ceil(Math.log2(maxZ) * depthSliceParam.x - depthSliceParam.y), this._zSlices);
	        return true;
	    }
	    _shrinkSpotLightByBoundOrth(halfX, halfY, near, far, viewLightPos, viewConeCap, radius, halfAngle, lightBound) {
	        var pbX = viewConeCap.x, pbY = viewConeCap.y, pbZ = viewConeCap.z;
	        var rb = Math.tan(halfAngle) * radius;
	        var paX = viewLightPos.x, paY = viewLightPos.y, paZ = viewLightPos.z;
	        var aX = pbX - paX, aY = pbY - paY, aZ = pbZ - paZ;
	        var dotA = aX * aX + aY * aY + aZ * aZ;
	        var eZ = Math.sqrt(1.0 - aZ * aZ / dotA);
	        var minZ = Math.max(Math.min(paZ, pbZ - eZ * rb), viewLightPos.z - radius);
	        var maxZ = Math.min(Math.max(paZ, pbZ + eZ * rb), viewLightPos.z + radius);
	        if ((minZ > far) || (maxZ <= near))
	            return false;
	        var eX = Math.sqrt(1.0 - aX * aX / dotA);
	        var minX = Math.max(Math.min(paX, pbX - eX * rb), viewLightPos.x - radius);
	        var maxX = Math.min(Math.max(paX, pbX + eX * rb), viewLightPos.x + radius);
	        if ((minX > halfX) || (maxX <= -halfX))
	            return false;
	        var eY = Math.sqrt(1.0 - aY * aY / dotA);
	        var minY = Math.max(Math.min(paY, pbY - eY * rb), viewLightPos.y - radius);
	        var maxY = Math.min(Math.max(paY, pbY + eY * rb), viewLightPos.y + radius);
	        if ((minY > halfY) || (maxY <= -halfY))
	            return false;
	        var xSlices = this._xSlices, ySlices = this._ySlices;
	        var depthSliceParam = this._depthSliceParam;
	        var xStride = halfX * 2 / xSlices, yStride = halfY * 2 / ySlices;
	        lightBound.xMin = Math.max(Math.floor((minX + halfX) / xStride), 0);
	        lightBound.xMax = Math.min(Math.ceil((maxX + halfX) / xStride), xSlices);
	        lightBound.yMin = Math.max(Math.floor((halfY - maxY) / yStride), 0);
	        lightBound.yMax = Math.min(Math.ceil((halfY - minY) / yStride), ySlices);
	        lightBound.zMin = Math.floor(Math.log2(Math.max(minZ, near)) * depthSliceParam.x - depthSliceParam.y);
	        lightBound.zMax = Math.min(Math.ceil(Math.log2(maxZ) * depthSliceParam.x - depthSliceParam.y), this._zSlices);
	        return true;
	    }
	    _shrinkXYByRadiusPerspective(lightviewPos, radius, lightBound, xPlanes, yPlanes) {
	        var xMin, yMin;
	        var xMax, yMax;
	        var lvX = lightviewPos.x, lvY = lightviewPos.y, lvZ = lightviewPos.z;
	        var i;
	        var n = this._ySlices + 1;
	        for (i = 0; i < n; i++) {
	            var plane = yPlanes[i];
	            if (lvY * plane.y + lvZ * plane.z < radius) {
	                yMin = Math.max(0, i - 1);
	                break;
	            }
	        }
	        if (i == n)
	            return false;
	        yMax = this._ySlices;
	        for (i = yMin + 1; i < n; i++) {
	            var plane = yPlanes[i];
	            if (lvY * plane.y + lvZ * plane.z <= -radius) {
	                yMax = Math.max(0, i);
	                break;
	            }
	        }
	        n = this._xSlices + 1;
	        for (i = 0; i < n; i++) {
	            var plane = xPlanes[i];
	            if (lvX * plane.x + lvZ * plane.z < radius) {
	                xMin = Math.max(0, i - 1);
	                break;
	            }
	        }
	        xMax = this._xSlices;
	        for (i = xMin + 1; i < n; i++) {
	            var plane = xPlanes[i];
	            if (lvX * plane.x + lvZ * plane.z <= -radius) {
	                xMax = Math.max(0, i);
	                break;
	            }
	        }
	        lightBound.xMin = xMin;
	        lightBound.xMax = xMax;
	        lightBound.yMin = yMin;
	        lightBound.yMax = yMax;
	        return true;
	    }
	    _shrinkSpotXYByConePerspective(lightviewPos, viewForward, radius, halfAngle, lightBound, xPlanes, yPlanes) {
	        var xMin, yMin;
	        var xMax, yMax;
	        var normal = Cluster._tempVector32;
	        var n = lightBound.yMax + 1;
	        for (var i = lightBound.yMin + 1; i < n; i++) {
	            if (this._insertConePlane(lightviewPos, viewForward, radius, halfAngle, yPlanes[i])) {
	                yMin = Math.max(0, i - 1);
	                break;
	            }
	        }
	        yMax = lightBound.yMax;
	        for (var i = yMin + 1; i < n; i++) {
	            var plane = yPlanes[i];
	            normal.setValue(0, -plane.y, -plane.z);
	            if (!this._insertConePlane(lightviewPos, viewForward, radius, halfAngle, normal)) {
	                yMax = Math.max(0, i);
	                break;
	            }
	        }
	        n = lightBound.xMax + 1;
	        for (var i = lightBound.xMin + 1; i < n; i++) {
	            if (this._insertConePlane(lightviewPos, viewForward, radius, halfAngle, xPlanes[i])) {
	                xMin = Math.max(0, i - 1);
	                break;
	            }
	        }
	        xMax = lightBound.xMax;
	        for (var i = xMin + 1; i < n; i++) {
	            var plane = xPlanes[i];
	            normal.setValue(-plane.x, 0, -plane.z);
	            if (!this._insertConePlane(lightviewPos, viewForward, radius, halfAngle, normal)) {
	                xMax = Math.max(0, i);
	                break;
	            }
	        }
	        lightBound.xMin = xMin;
	        lightBound.xMax = xMax;
	        lightBound.yMin = yMin;
	        lightBound.yMax = yMax;
	    }
	    _updatePointLightPerspective(near, far, viewMat, pointLight, lightIndex, xPlanes, yPlanes) {
	        var lightBound = Cluster._tempLightBound;
	        var lightviewPos = Cluster._tempVector30;
	        Vector3.transformV3ToV3(pointLight._transform.position, viewMat, lightviewPos);
	        lightviewPos.z *= -1;
	        if (!this._shrinkSphereLightZPerspective(near, far, lightviewPos, pointLight.range, lightBound))
	            return;
	        if (!this._shrinkXYByRadiusPerspective(lightviewPos, pointLight.range, lightBound, xPlanes, yPlanes))
	            return;
	        this._placePointLightToClusters(lightIndex, lightBound);
	    }
	    _updateSpotLightPerspective(near, far, viewMat, spotLight, lightIndex, xPlanes, yPlanes) {
	        var lightBound = Cluster._tempLightBound;
	        var viewPos = Cluster._tempVector30;
	        var forward = Cluster._tempVector31;
	        var viewConeCap = Cluster._tempVector34;
	        var position = spotLight._transform.position;
	        var range = spotLight.range;
	        spotLight._transform.worldMatrix.getForward(forward);
	        Vector3.normalize(forward, forward);
	        Vector3.scale(forward, range, viewConeCap);
	        Vector3.add(position, viewConeCap, viewConeCap);
	        Vector3.transformV3ToV3(position, viewMat, viewPos);
	        Vector3.transformV3ToV3(viewConeCap, viewMat, viewConeCap);
	        viewPos.z *= -1;
	        viewConeCap.z *= -1;
	        var halfAngle = (spotLight.spotAngle / 2) * Math.PI / 180;
	        if (!this._shrinkSpotLightZPerspective(near, far, viewPos, viewConeCap, range, halfAngle, lightBound))
	            return;
	        if (!this._shrinkXYByRadiusPerspective(viewPos, range, lightBound, xPlanes, yPlanes))
	            return;
	        var viewFor = Cluster._tempVector33;
	        viewFor.x = viewConeCap.x - viewPos.x, viewFor.y = viewConeCap.y - viewPos.y, viewFor.z = viewConeCap.z - viewPos.z;
	        Vector3.normalize(viewFor, viewFor);
	        this._shrinkSpotXYByConePerspective(viewPos, viewFor, range, halfAngle, lightBound, xPlanes, yPlanes);
	        this._placeSpotLightToClusters(lightIndex, lightBound);
	    }
	    _updatePointLightOrth(halfX, halfY, near, far, viewMat, pointLight, lightIndex) {
	        var lightBound = Cluster._tempLightBound;
	        var lightviewPos = Cluster._tempVector30;
	        Vector3.transformV3ToV3(pointLight._transform.position, viewMat, lightviewPos);
	        lightviewPos.z *= -1;
	        if (!this._shrinkSphereLightByBoundOrth(halfX, halfY, near, far, lightviewPos, pointLight.range, lightBound))
	            return;
	        this._placePointLightToClusters(lightIndex, lightBound);
	    }
	    _updateSpotLightOrth(halfX, halfY, near, far, viewMat, spotLight, lightIndex) {
	        var lightBound = Cluster._tempLightBound;
	        var viewPos = Cluster._tempVector30;
	        var forward = Cluster._tempVector31;
	        var viewConeCap = Cluster._tempVector34;
	        var position = spotLight._transform.position;
	        var range = spotLight.range;
	        spotLight._transform.worldMatrix.getForward(forward);
	        Vector3.normalize(forward, forward);
	        Vector3.scale(forward, range, viewConeCap);
	        Vector3.add(position, viewConeCap, viewConeCap);
	        Vector3.transformV3ToV3(position, viewMat, viewPos);
	        Vector3.transformV3ToV3(viewConeCap, viewMat, viewConeCap);
	        viewPos.z *= -1;
	        viewConeCap.z *= -1;
	        var halfAngle = (spotLight.spotAngle / 2) * Math.PI / 180;
	        if (!this._shrinkSpotLightByBoundOrth(halfX, halfY, near, far, viewPos, viewConeCap, range, halfAngle, lightBound))
	            return;
	        this._placeSpotLightToClusters(lightIndex, lightBound);
	    }
	    update(camera, scene) {
	        this._updateMark++;
	        var camNear = camera.nearPlane;
	        this._depthSliceParam.x = Config3D._config.lightClusterCount.z / Math.log2(camera.farPlane / camNear);
	        this._depthSliceParam.y = Math.log2(camNear) * this._depthSliceParam.x;
	        var near = camera.nearPlane;
	        var far = camera.farPlane;
	        var viewMat = camera.viewMatrix;
	        var curCount = scene._directionLights._length;
	        var pointLights = scene._pointLights;
	        var poiCount = pointLights._length;
	        var poiElements = pointLights._elements;
	        var spotLights = scene._spotLights;
	        var spoCount = spotLights._length;
	        var spoElements = spotLights._elements;
	        if (camera.orthographic) {
	            var halfY = camera.orthographicVerticalSize / 2.0;
	            var halfX = halfY * camera.aspectRatio;
	            for (var i = 0; i < poiCount; i++, curCount++)
	                this._updatePointLightOrth(halfX, halfY, near, far, viewMat, poiElements[i], curCount);
	            for (var i = 0; i < spoCount; i++, curCount++)
	                this._updateSpotLightOrth(halfX, halfY, near, far, viewMat, spoElements[i], curCount);
	        }
	        else {
	            camera._updateClusterPlaneXY();
	            var xPlanes = camera._clusterXPlanes;
	            var yPlanes = camera._clusterYPlanes;
	            for (var i = 0; i < poiCount; i++, curCount++)
	                this._updatePointLightPerspective(near, far, viewMat, poiElements[i], curCount, xPlanes, yPlanes);
	            for (var i = 0; i < spoCount; i++, curCount++)
	                this._updateSpotLightPerspective(near, far, viewMat, spoElements[i], curCount, xPlanes, yPlanes);
	        }
	        if (poiCount + spoCount > 0) {
	            var xSlices = this._xSlices, ySlices = this._ySlices, zSlices = this._zSlices;
	            var widthFloat = xSlices * ySlices * 4;
	            var lightOff = widthFloat * zSlices;
	            var clusterPixels = this._clusterPixels;
	            var clusterPixelsCount = clusterPixels.length;
	            var clusterDatas = this._clusterDatas;
	            var updateMark = this._updateMark;
	            var freeSpace = true;
	            for (var z = 0; z < zSlices; z++) {
	                for (var y = 0; y < ySlices; y++) {
	                    for (var x = 0; x < xSlices; x++) {
	                        var data = clusterDatas[z][y][x];
	                        var clusterOff = (x + y * xSlices + z * xSlices * ySlices) * 4;
	                        if (data.updateMark !== updateMark) {
	                            clusterPixels[clusterOff] = 0;
	                            clusterPixels[clusterOff + 1] = 0;
	                        }
	                        else {
	                            if (freeSpace) {
	                                var indices = data.indices;
	                                var pCount = data.pointLightCount;
	                                var sCount = data.spotLightCount;
	                                var count = pCount + sCount;
	                                if (lightOff + count < clusterPixelsCount) {
	                                    clusterPixels[clusterOff] = pCount;
	                                    clusterPixels[clusterOff + 1] = sCount;
	                                    clusterPixels[clusterOff + 2] = Math.floor(lightOff / widthFloat);
	                                    clusterPixels[clusterOff + 3] = lightOff % widthFloat;
	                                    for (var i = 0; i < count; i++)
	                                        clusterPixels[lightOff++] = indices[i];
	                                }
	                                else {
	                                    count = clusterPixelsCount - (lightOff + count);
	                                    pCount = Math.min(pCount, count);
	                                    clusterPixels[clusterOff] = pCount;
	                                    clusterPixels[clusterOff + 1] = Math.min(sCount, count - pCount);
	                                    clusterPixels[clusterOff + 2] = Math.floor(lightOff / widthFloat);
	                                    clusterPixels[clusterOff + 3] = lightOff % widthFloat;
	                                    for (var i = 0; i < count; i++)
	                                        clusterPixels[lightOff++] = indices[i];
	                                    freeSpace = false;
	                                }
	                            }
	                        }
	                    }
	                }
	            }
	            var width = this._clusterTexture.width;
	            this._clusterTexture.setSubPixels(0, 0, width, Math.ceil(lightOff / (4 * width)), clusterPixels);
	        }
	    }
	}
	Cluster._tempVector30 = new Vector3();
	Cluster._tempVector31 = new Vector3();
	Cluster._tempVector32 = new Vector3();
	Cluster._tempVector33 = new Vector3();
	Cluster._tempVector34 = new Vector3();
	Cluster._tempVector35 = new Vector3();
	Cluster._tempVector36 = new Vector3();
	Cluster._tempVector37 = new Vector3();
	Cluster._tempLightBound = new LightBound();

	class Plane {
	    constructor(normal, d = 0) {
	        this.normal = normal;
	        this.distance = d;
	    }
	    static createPlaneBy3P(point1, point2, point3) {
	        var x1 = point2.x - point1.x;
	        var y1 = point2.y - point1.y;
	        var z1 = point2.z - point1.z;
	        var x2 = point3.x - point1.x;
	        var y2 = point3.y - point1.y;
	        var z2 = point3.z - point1.z;
	        var yz = (y1 * z2) - (z1 * y2);
	        var xz = (z1 * x2) - (x1 * z2);
	        var xy = (x1 * y2) - (y1 * x2);
	        var invPyth = 1 / (Math.sqrt((yz * yz) + (xz * xz) + (xy * xy)));
	        var x = yz * invPyth;
	        var y = xz * invPyth;
	        var z = xy * invPyth;
	        Plane._TEMPVec3.x = x;
	        Plane._TEMPVec3.y = y;
	        Plane._TEMPVec3.z = z;
	        var d = -((x * point1.x) + (y * point1.y) + (z * point1.z));
	        var plane = new Plane(Plane._TEMPVec3, d);
	        return plane;
	    }
	    normalize() {
	        var normalEX = this.normal.x;
	        var normalEY = this.normal.y;
	        var normalEZ = this.normal.z;
	        var magnitude = 1 / Math.sqrt(normalEX * normalEX + normalEY * normalEY + normalEZ * normalEZ);
	        this.normal.x = normalEX * magnitude;
	        this.normal.y = normalEY * magnitude;
	        this.normal.z = normalEZ * magnitude;
	        this.distance *= magnitude;
	    }
	}
	Plane._TEMPVec3 = new Vector3();
	Plane.PlaneIntersectionType_Back = 0;
	Plane.PlaneIntersectionType_Front = 1;
	Plane.PlaneIntersectionType_Intersecting = 2;

	class Ray {
	    constructor(origin, direction) {
	        this.origin = origin;
	        this.direction = direction;
	    }
	}

	class ContainmentType {
	}
	ContainmentType.Disjoint = 0;
	ContainmentType.Contains = 1;
	ContainmentType.Intersects = 2;

	class CollisionUtils {
	    constructor() {
	    }
	    static distancePlaneToPoint(plane, point) {
	        var dot = Vector3.dot(plane.normal, point);
	        return dot - plane.distance;
	    }
	    static distanceBoxToPoint(box, point) {
	        var boxMin = box.min;
	        var boxMineX = boxMin.x;
	        var boxMineY = boxMin.y;
	        var boxMineZ = boxMin.z;
	        var boxMax = box.max;
	        var boxMaxeX = boxMax.x;
	        var boxMaxeY = boxMax.y;
	        var boxMaxeZ = boxMax.z;
	        var pointeX = point.x;
	        var pointeY = point.y;
	        var pointeZ = point.z;
	        var distance = 0;
	        if (pointeX < boxMineX)
	            distance += (boxMineX - pointeX) * (boxMineX - pointeX);
	        if (pointeX > boxMaxeX)
	            distance += (boxMaxeX - pointeX) * (boxMaxeX - pointeX);
	        if (pointeY < boxMineY)
	            distance += (boxMineY - pointeY) * (boxMineY - pointeY);
	        if (pointeY > boxMaxeY)
	            distance += (boxMaxeY - pointeY) * (boxMaxeY - pointeY);
	        if (pointeZ < boxMineZ)
	            distance += (boxMineZ - pointeZ) * (boxMineZ - pointeZ);
	        if (pointeZ > boxMaxeZ)
	            distance += (boxMaxeZ - pointeZ) * (boxMaxeZ - pointeZ);
	        return Math.sqrt(distance);
	    }
	    static distanceBoxToBox(box1, box2) {
	        var box1Mine = box1.min;
	        var box1MineX = box1Mine.x;
	        var box1MineY = box1Mine.y;
	        var box1MineZ = box1Mine.z;
	        var box1Maxe = box1.max;
	        var box1MaxeX = box1Maxe.x;
	        var box1MaxeY = box1Maxe.y;
	        var box1MaxeZ = box1Maxe.z;
	        var box2Mine = box2.min;
	        var box2MineX = box2Mine.x;
	        var box2MineY = box2Mine.y;
	        var box2MineZ = box2Mine.z;
	        var box2Maxe = box2.max;
	        var box2MaxeX = box2Maxe.x;
	        var box2MaxeY = box2Maxe.y;
	        var box2MaxeZ = box2Maxe.z;
	        var distance = 0;
	        var delta;
	        if (box1MineX > box2MaxeX) {
	            delta = box1MineX - box2MaxeX;
	            distance += delta * delta;
	        }
	        else if (box2MineX > box1MaxeX) {
	            delta = box2MineX - box1MaxeX;
	            distance += delta * delta;
	        }
	        if (box1MineY > box2MaxeY) {
	            delta = box1MineY - box2MaxeY;
	            distance += delta * delta;
	        }
	        else if (box2MineY > box1MaxeY) {
	            delta = box2MineY - box1MaxeY;
	            distance += delta * delta;
	        }
	        if (box1MineZ > box2MaxeZ) {
	            delta = box1MineZ - box2MaxeZ;
	            distance += delta * delta;
	        }
	        else if (box2MineZ > box1MaxeZ) {
	            delta = box2MineZ - box1MaxeZ;
	            distance += delta * delta;
	        }
	        return Math.sqrt(distance);
	    }
	    static distanceSphereToPoint(sphere, point) {
	        var distance = Math.sqrt(Vector3.distanceSquared(sphere.center, point));
	        distance -= sphere.radius;
	        return Math.max(distance, 0);
	    }
	    static distanceSphereToSphere(sphere1, sphere2) {
	        var distance = Math.sqrt(Vector3.distanceSquared(sphere1.center, sphere2.center));
	        distance -= sphere1.radius + sphere2.radius;
	        return Math.max(distance, 0);
	    }
	    static intersectsRayAndTriangleRD(ray, vertex1, vertex2, vertex3, out) {
	        var rayO = ray.origin;
	        var rayOeX = rayO.x;
	        var rayOeY = rayO.y;
	        var rayOeZ = rayO.z;
	        var rayD = ray.direction;
	        var rayDeX = rayD.x;
	        var rayDeY = rayD.y;
	        var rayDeZ = rayD.z;
	        var v1eX = vertex1.x;
	        var v1eY = vertex1.y;
	        var v1eZ = vertex1.z;
	        var v2eX = vertex2.x;
	        var v2eY = vertex2.y;
	        var v2eZ = vertex2.z;
	        var v3eX = vertex3.x;
	        var v3eY = vertex3.y;
	        var v3eZ = vertex3.z;
	        var _tempV30eX = CollisionUtils._tempV30.x;
	        var _tempV30eY = CollisionUtils._tempV30.y;
	        var _tempV30eZ = CollisionUtils._tempV30.z;
	        _tempV30eX = v2eX - v1eX;
	        _tempV30eY = v2eY - v1eY;
	        _tempV30eZ = v2eZ - v1eZ;
	        var _tempV31eX = CollisionUtils._tempV31.x;
	        var _tempV31eY = CollisionUtils._tempV31.y;
	        var _tempV31eZ = CollisionUtils._tempV31.z;
	        _tempV31eX = v3eX - v1eX;
	        _tempV31eY = v3eY - v1eY;
	        _tempV31eZ = v3eZ - v1eZ;
	        var _tempV32eX = CollisionUtils._tempV32.x;
	        var _tempV32eY = CollisionUtils._tempV32.y;
	        var _tempV32eZ = CollisionUtils._tempV32.z;
	        _tempV32eX = (rayDeY * _tempV31eZ) - (rayDeZ * _tempV31eY);
	        _tempV32eY = (rayDeZ * _tempV31eX) - (rayDeX * _tempV31eZ);
	        _tempV32eZ = (rayDeX * _tempV31eY) - (rayDeY * _tempV31eX);
	        var determinant = (_tempV30eX * _tempV32eX) + (_tempV30eY * _tempV32eY) + (_tempV30eZ * _tempV32eZ);
	        if (MathUtils3D.isZero(determinant)) {
	            return false;
	        }
	        var inversedeterminant = 1 / determinant;
	        var _tempV33eX = CollisionUtils._tempV33.x;
	        var _tempV33eY = CollisionUtils._tempV33.y;
	        var _tempV33eZ = CollisionUtils._tempV33.z;
	        _tempV33eX = rayOeX - v1eX;
	        _tempV33eY = rayOeY - v1eY;
	        _tempV33eZ = rayOeZ - v1eZ;
	        var triangleU = (_tempV33eX * _tempV32eX) + (_tempV33eY * _tempV32eY) + (_tempV33eZ * _tempV32eZ);
	        triangleU *= inversedeterminant;
	        if (triangleU < 0 || triangleU > 1) {
	            return false;
	        }
	        var _tempV34eX = CollisionUtils._tempV34.x;
	        var _tempV34eY = CollisionUtils._tempV34.y;
	        var _tempV34eZ = CollisionUtils._tempV34.z;
	        _tempV34eX = (_tempV33eY * _tempV30eZ) - (_tempV33eZ * _tempV30eY);
	        _tempV34eY = (_tempV33eZ * _tempV30eX) - (_tempV33eX * _tempV30eZ);
	        _tempV34eZ = (_tempV33eX * _tempV30eY) - (_tempV33eY * _tempV30eX);
	        var triangleV = ((rayDeX * _tempV34eX) + (rayDeY * _tempV34eY)) + (rayDeZ * _tempV34eZ);
	        triangleV *= inversedeterminant;
	        if (triangleV < 0 || triangleU + triangleV > 1) {
	            return false;
	        }
	        var raydistance = (_tempV31eX * _tempV34eX) + (_tempV31eY * _tempV34eY) + (_tempV31eZ * _tempV34eZ);
	        raydistance *= inversedeterminant;
	        if (raydistance < 0) {
	            return false;
	        }
	        return true;
	    }
	    static intersectsRayAndTriangleRP(ray, vertex1, vertex2, vertex3, out) {
	        var distance;
	        if (!CollisionUtils.intersectsRayAndTriangleRD(ray, vertex1, vertex2, vertex3, distance)) {
	            out = Vector3._ZERO;
	            return false;
	        }
	        Vector3.scale(ray.direction, distance, CollisionUtils._tempV30);
	        Vector3.add(ray.origin, CollisionUtils._tempV30, out);
	        return true;
	    }
	    static intersectsRayAndPoint(ray, point) {
	        Vector3.subtract(ray.origin, point, CollisionUtils._tempV30);
	        var b = Vector3.dot(CollisionUtils._tempV30, ray.direction);
	        var c = Vector3.dot(CollisionUtils._tempV30, CollisionUtils._tempV30) - MathUtils3D.zeroTolerance;
	        if (c > 0 && b > 0)
	            return false;
	        var discriminant = b * b - c;
	        if (discriminant < 0)
	            return false;
	        return true;
	    }
	    static intersectsRayAndRay(ray1, ray2, out) {
	        var ray1o = ray1.origin;
	        var ray1oeX = ray1o.x;
	        var ray1oeY = ray1o.y;
	        var ray1oeZ = ray1o.z;
	        var ray1d = ray1.direction;
	        var ray1deX = ray1d.x;
	        var ray1deY = ray1d.y;
	        var ray1deZ = ray1d.z;
	        var ray2o = ray2.origin;
	        var ray2oeX = ray2o.x;
	        var ray2oeY = ray2o.y;
	        var ray2oeZ = ray2o.z;
	        var ray2d = ray2.direction;
	        var ray2deX = ray2d.x;
	        var ray2deY = ray2d.y;
	        var ray2deZ = ray2d.z;
	        Vector3.cross(ray1d, ray2d, CollisionUtils._tempV30);
	        var tempV3 = CollisionUtils._tempV30;
	        var denominator = Vector3.scalarLength(CollisionUtils._tempV30);
	        if (MathUtils3D.isZero(denominator)) {
	            if (MathUtils3D.nearEqual(ray2oeX, ray1oeX) && MathUtils3D.nearEqual(ray2oeY, ray1oeY) && MathUtils3D.nearEqual(ray2oeZ, ray1oeZ)) {
	                return true;
	            }
	        }
	        denominator = denominator * denominator;
	        var m11 = ray2oeX - ray1oeX;
	        var m12 = ray2oeY - ray1oeY;
	        var m13 = ray2oeZ - ray1oeZ;
	        var m21 = ray2deX;
	        var m22 = ray2deY;
	        var m23 = ray2deZ;
	        var m31 = tempV3.x;
	        var m32 = tempV3.y;
	        var m33 = tempV3.z;
	        var dets = m11 * m22 * m33 + m12 * m23 * m31 + m13 * m21 * m32 - m11 * m23 * m32 - m12 * m21 * m33 - m13 * m22 * m31;
	        m21 = ray1deX;
	        m22 = ray1deY;
	        m23 = ray1deZ;
	        var s = dets / denominator;
	        Vector3.scale(ray1d, s, CollisionUtils._tempV30);
	        Vector3.scale(ray2d, s, CollisionUtils._tempV31);
	        Vector3.add(ray1o, CollisionUtils._tempV30, CollisionUtils._tempV32);
	        Vector3.add(ray2o, CollisionUtils._tempV31, CollisionUtils._tempV33);
	        var point1e = CollisionUtils._tempV32;
	        var point2e = CollisionUtils._tempV33;
	        if (!MathUtils3D.nearEqual(point2e.x, point1e.x) || !MathUtils3D.nearEqual(point2e.y, point1e.y) || !MathUtils3D.nearEqual(point2e.z, point1e.z)) {
	            return false;
	        }
	        return true;
	    }
	    static intersectsPlaneAndTriangle(plane, vertex1, vertex2, vertex3) {
	        var test1 = CollisionUtils.intersectsPlaneAndPoint(plane, vertex1);
	        var test2 = CollisionUtils.intersectsPlaneAndPoint(plane, vertex2);
	        var test3 = CollisionUtils.intersectsPlaneAndPoint(plane, vertex3);
	        if (test1 == Plane.PlaneIntersectionType_Front && test2 == Plane.PlaneIntersectionType_Front && test3 == Plane.PlaneIntersectionType_Front)
	            return Plane.PlaneIntersectionType_Front;
	        if (test1 == Plane.PlaneIntersectionType_Back && test2 == Plane.PlaneIntersectionType_Back && test3 == Plane.PlaneIntersectionType_Back)
	            return Plane.PlaneIntersectionType_Back;
	        return Plane.PlaneIntersectionType_Intersecting;
	    }
	    static intersectsRayAndPlaneRD(ray, plane, out) {
	        var planeNor = plane.normal;
	        var direction = Vector3.dot(planeNor, ray.direction);
	        if (MathUtils3D.isZero(direction)) {
	            out = 0;
	            return false;
	        }
	        var position = Vector3.dot(planeNor, ray.origin);
	        out = (-plane.distance - position) / direction;
	        if (out < 0) {
	            out = 0;
	            return false;
	        }
	        return true;
	    }
	    static intersectsRayAndPlaneRP(ray, plane, out) {
	        var distance;
	        if (!CollisionUtils.intersectsRayAndPlaneRD(ray, plane, distance)) {
	            return false;
	        }
	        Vector3.scale(ray.direction, distance, CollisionUtils._tempV30);
	        Vector3.add(ray.origin, CollisionUtils._tempV30, CollisionUtils._tempV31);
	        return true;
	    }
	    static intersectsRayAndBoxRD(ray, box) {
	        var rayoe = ray.origin;
	        var rayoeX = rayoe.x;
	        var rayoeY = rayoe.y;
	        var rayoeZ = rayoe.z;
	        var rayde = ray.direction;
	        var raydeX = rayde.x;
	        var raydeY = rayde.y;
	        var raydeZ = rayde.z;
	        var boxMine = box.min;
	        var boxMineX = boxMine.x;
	        var boxMineY = boxMine.y;
	        var boxMineZ = boxMine.z;
	        var boxMaxe = box.max;
	        var boxMaxeX = boxMaxe.x;
	        var boxMaxeY = boxMaxe.y;
	        var boxMaxeZ = boxMaxe.z;
	        var out = 0;
	        var tmax = MathUtils3D.MaxValue;
	        if (MathUtils3D.isZero(raydeX)) {
	            if (rayoeX < boxMineX || rayoeX > boxMaxeX) {
	                return -1;
	            }
	        }
	        else {
	            var inverse = 1 / raydeX;
	            var t1 = (boxMineX - rayoeX) * inverse;
	            var t2 = (boxMaxeX - rayoeX) * inverse;
	            if (t1 > t2) {
	                var temp = t1;
	                t1 = t2;
	                t2 = temp;
	            }
	            out = Math.max(t1, out);
	            tmax = Math.min(t2, tmax);
	            if (out > tmax) {
	                return -1;
	            }
	        }
	        if (MathUtils3D.isZero(raydeY)) {
	            if (rayoeY < boxMineY || rayoeY > boxMaxeY) {
	                return -1;
	            }
	        }
	        else {
	            var inverse1 = 1 / raydeY;
	            var t3 = (boxMineY - rayoeY) * inverse1;
	            var t4 = (boxMaxeY - rayoeY) * inverse1;
	            if (t3 > t4) {
	                var temp1 = t3;
	                t3 = t4;
	                t4 = temp1;
	            }
	            out = Math.max(t3, out);
	            tmax = Math.min(t4, tmax);
	            if (out > tmax) {
	                return -1;
	            }
	        }
	        if (MathUtils3D.isZero(raydeZ)) {
	            if (rayoeZ < boxMineZ || rayoeZ > boxMaxeZ) {
	                return -1;
	            }
	        }
	        else {
	            var inverse2 = 1 / raydeZ;
	            var t5 = (boxMineZ - rayoeZ) * inverse2;
	            var t6 = (boxMaxeZ - rayoeZ) * inverse2;
	            if (t5 > t6) {
	                var temp2 = t5;
	                t5 = t6;
	                t6 = temp2;
	            }
	            out = Math.max(t5, out);
	            tmax = Math.min(t6, tmax);
	            if (out > tmax) {
	                return -1;
	            }
	        }
	        return out;
	    }
	    static intersectsRayAndBoxRP(ray, box, out) {
	        var distance = CollisionUtils.intersectsRayAndBoxRD(ray, box);
	        if (distance === -1) {
	            Vector3._ZERO.cloneTo(out);
	            return distance;
	        }
	        Vector3.scale(ray.direction, distance, CollisionUtils._tempV30);
	        Vector3.add(ray.origin, CollisionUtils._tempV30, CollisionUtils._tempV31);
	        CollisionUtils._tempV31.cloneTo(out);
	        return distance;
	    }
	    static intersectsRayAndSphereRD(ray, sphere) {
	        var sphereR = sphere.radius;
	        Vector3.subtract(ray.origin, sphere.center, CollisionUtils._tempV30);
	        var b = Vector3.dot(CollisionUtils._tempV30, ray.direction);
	        var c = Vector3.dot(CollisionUtils._tempV30, CollisionUtils._tempV30) - (sphereR * sphereR);
	        if (c > 0 && b > 0) {
	            return -1;
	        }
	        var discriminant = b * b - c;
	        if (discriminant < 0) {
	            return -1;
	        }
	        var distance = -b - Math.sqrt(discriminant);
	        if (distance < 0)
	            distance = 0;
	        return distance;
	    }
	    static intersectsRayAndSphereRP(ray, sphere, out) {
	        var distance = CollisionUtils.intersectsRayAndSphereRD(ray, sphere);
	        if (distance === -1) {
	            Vector3._ZERO.cloneTo(out);
	            return distance;
	        }
	        Vector3.scale(ray.direction, distance, CollisionUtils._tempV30);
	        Vector3.add(ray.origin, CollisionUtils._tempV30, CollisionUtils._tempV31);
	        CollisionUtils._tempV31.cloneTo(out);
	        return distance;
	    }
	    static intersectsSphereAndTriangle(sphere, vertex1, vertex2, vertex3) {
	        var sphereC = sphere.center;
	        var sphereR = sphere.radius;
	        CollisionUtils.closestPointPointTriangle(sphereC, vertex1, vertex2, vertex3, CollisionUtils._tempV30);
	        Vector3.subtract(CollisionUtils._tempV30, sphereC, CollisionUtils._tempV31);
	        var dot = Vector3.dot(CollisionUtils._tempV31, CollisionUtils._tempV31);
	        return dot <= sphereR * sphereR;
	    }
	    static intersectsPlaneAndPoint(plane, point) {
	        var distance = Vector3.dot(plane.normal, point) + plane.distance;
	        if (distance > 0)
	            return Plane.PlaneIntersectionType_Front;
	        if (distance < 0)
	            return Plane.PlaneIntersectionType_Back;
	        return Plane.PlaneIntersectionType_Intersecting;
	    }
	    static intersectsPlaneAndPlane(plane1, plane2) {
	        Vector3.cross(plane1.normal, plane2.normal, CollisionUtils._tempV30);
	        var denominator = Vector3.dot(CollisionUtils._tempV30, CollisionUtils._tempV30);
	        if (MathUtils3D.isZero(denominator))
	            return false;
	        return true;
	    }
	    static intersectsPlaneAndPlaneRL(plane1, plane2, line) {
	        var plane1nor = plane1.normal;
	        var plane2nor = plane2.normal;
	        Vector3.cross(plane1nor, plane2nor, CollisionUtils._tempV34);
	        var denominator = Vector3.dot(CollisionUtils._tempV34, CollisionUtils._tempV34);
	        if (MathUtils3D.isZero(denominator))
	            return false;
	        Vector3.scale(plane2nor, plane1.distance, CollisionUtils._tempV30);
	        Vector3.scale(plane1nor, plane2.distance, CollisionUtils._tempV31);
	        Vector3.subtract(CollisionUtils._tempV30, CollisionUtils._tempV31, CollisionUtils._tempV32);
	        Vector3.cross(CollisionUtils._tempV32, CollisionUtils._tempV34, CollisionUtils._tempV33);
	        Vector3.normalize(CollisionUtils._tempV34, CollisionUtils._tempV34);
	        return true;
	    }
	    static intersectsPlaneAndBox(plane, box) {
	        var planeD = plane.distance;
	        var planeNor = plane.normal;
	        var planeNoreX = planeNor.x;
	        var planeNoreY = planeNor.y;
	        var planeNoreZ = planeNor.z;
	        var boxMine = box.min;
	        var boxMineX = boxMine.x;
	        var boxMineY = boxMine.y;
	        var boxMineZ = boxMine.z;
	        var boxMaxe = box.max;
	        var boxMaxeX = boxMaxe.x;
	        var boxMaxeY = boxMaxe.y;
	        var boxMaxeZ = boxMaxe.z;
	        CollisionUtils._tempV30.x = (planeNoreX > 0) ? boxMineX : boxMaxeX;
	        CollisionUtils._tempV30.y = (planeNoreY > 0) ? boxMineY : boxMaxeY;
	        CollisionUtils._tempV30.z = (planeNoreZ > 0) ? boxMineZ : boxMaxeZ;
	        CollisionUtils._tempV31.x = (planeNoreX > 0) ? boxMaxeX : boxMineX;
	        CollisionUtils._tempV31.y = (planeNoreY > 0) ? boxMaxeY : boxMineY;
	        CollisionUtils._tempV31.z = (planeNoreZ > 0) ? boxMaxeZ : boxMineZ;
	        var distance = Vector3.dot(planeNor, CollisionUtils._tempV30);
	        if (distance + planeD > 0)
	            return Plane.PlaneIntersectionType_Front;
	        distance = Vector3.dot(planeNor, CollisionUtils._tempV31);
	        if (distance + planeD < 0)
	            return Plane.PlaneIntersectionType_Back;
	        return Plane.PlaneIntersectionType_Intersecting;
	    }
	    static intersectsPlaneAndSphere(plane, sphere) {
	        var sphereR = sphere.radius;
	        var distance = Vector3.dot(plane.normal, sphere.center) + plane.distance;
	        if (distance > sphereR)
	            return Plane.PlaneIntersectionType_Front;
	        if (distance < -sphereR)
	            return Plane.PlaneIntersectionType_Back;
	        return Plane.PlaneIntersectionType_Intersecting;
	    }
	    static intersectsBoxAndBox(box1, box2) {
	        var box1Mine = box1.min;
	        var box1Maxe = box1.max;
	        var box2Mine = box2.min;
	        var box2Maxe = box2.max;
	        if (box1Mine.x > box2Maxe.x || box2Mine.x > box1Maxe.x)
	            return false;
	        if (box1Mine.y > box2Maxe.y || box2Mine.y > box1Maxe.y)
	            return false;
	        if (box1Mine.z > box2Maxe.z || box2Mine.z > box1Maxe.z)
	            return false;
	        return true;
	    }
	    static intersectsBoxAndSphere(box, sphere) {
	        var sphereC = sphere.center;
	        var sphereR = sphere.radius;
	        Vector3.Clamp(sphereC, box.min, box.max, CollisionUtils._tempV30);
	        var distance = Vector3.distanceSquared(sphereC, CollisionUtils._tempV30);
	        return distance <= sphereR * sphereR;
	    }
	    static intersectsSphereAndSphere(sphere1, sphere2) {
	        var radiisum = sphere1.radius + sphere2.radius;
	        return Vector3.distanceSquared(sphere1.center, sphere2.center) <= radiisum * radiisum;
	    }
	    static boxContainsPoint(box, point) {
	        var boxMine = box.min;
	        var boxMaxe = box.max;
	        if (boxMine.x <= point.x && boxMaxe.x >= point.x && boxMine.y <= point.y && boxMaxe.y >= point.y && boxMine.z <= point.z && boxMaxe.z >= point.z)
	            return ContainmentType.Contains;
	        return ContainmentType.Disjoint;
	    }
	    static boxContainsBox(box1, box2) {
	        var box1Mine = box1.min;
	        var box1MineX = box1Mine.x;
	        var box1MineY = box1Mine.y;
	        var box1MineZ = box1Mine.z;
	        var box1Maxe = box1.max;
	        var box1MaxeX = box1Maxe.x;
	        var box1MaxeY = box1Maxe.y;
	        var box1MaxeZ = box1Maxe.z;
	        var box2Mine = box2.min;
	        var box2MineX = box2Mine.x;
	        var box2MineY = box2Mine.y;
	        var box2MineZ = box2Mine.z;
	        var box2Maxe = box2.max;
	        var box2MaxeX = box2Maxe.x;
	        var box2MaxeY = box2Maxe.y;
	        var box2MaxeZ = box2Maxe.z;
	        if (box1MaxeX < box2MineX || box1MineX > box2MaxeX)
	            return ContainmentType.Disjoint;
	        if (box1MaxeY < box2MineY || box1MineY > box2MaxeY)
	            return ContainmentType.Disjoint;
	        if (box1MaxeZ < box2MineZ || box1MineZ > box2MaxeZ)
	            return ContainmentType.Disjoint;
	        if (box1MineX <= box2MineX && box2MaxeX <= box1MaxeX && box1MineY <= box2MineY && box2MaxeY <= box1MaxeY && box1MineZ <= box2MineZ && box2MaxeZ <= box1MaxeZ) {
	            return ContainmentType.Contains;
	        }
	        return ContainmentType.Intersects;
	    }
	    static boxContainsSphere(box, sphere) {
	        var boxMin = box.min;
	        var boxMineX = boxMin.x;
	        var boxMineY = boxMin.y;
	        var boxMineZ = boxMin.z;
	        var boxMax = box.max;
	        var boxMaxeX = boxMax.x;
	        var boxMaxeY = boxMax.y;
	        var boxMaxeZ = boxMax.z;
	        var sphereC = sphere.center;
	        var sphereCeX = sphereC.x;
	        var sphereCeY = sphereC.y;
	        var sphereCeZ = sphereC.z;
	        var sphereR = sphere.radius;
	        Vector3.Clamp(sphereC, boxMin, boxMax, CollisionUtils._tempV30);
	        var distance = Vector3.distanceSquared(sphereC, CollisionUtils._tempV30);
	        if (distance > sphereR * sphereR)
	            return ContainmentType.Disjoint;
	        if ((((boxMineX + sphereR <= sphereCeX) && (sphereCeX <= boxMaxeX - sphereR)) && ((boxMaxeX - boxMineX > sphereR) &&
	            (boxMineY + sphereR <= sphereCeY))) && (((sphereCeY <= boxMaxeY - sphereR) && (boxMaxeY - boxMineY > sphereR)) &&
	            (((boxMineZ + sphereR <= sphereCeZ) && (sphereCeZ <= boxMaxeZ - sphereR)) && (boxMaxeZ - boxMineZ > sphereR))))
	            return ContainmentType.Contains;
	        return ContainmentType.Intersects;
	    }
	    static sphereContainsPoint(sphere, point) {
	        if (Vector3.distanceSquared(point, sphere.center) <= sphere.radius * sphere.radius)
	            return ContainmentType.Contains;
	        return ContainmentType.Disjoint;
	    }
	    static sphereContainsTriangle(sphere, vertex1, vertex2, vertex3) {
	        var test1 = CollisionUtils.sphereContainsPoint(sphere, vertex1);
	        var test2 = CollisionUtils.sphereContainsPoint(sphere, vertex2);
	        var test3 = CollisionUtils.sphereContainsPoint(sphere, vertex3);
	        if (test1 == ContainmentType.Contains && test2 == ContainmentType.Contains && test3 == ContainmentType.Contains)
	            return ContainmentType.Contains;
	        if (CollisionUtils.intersectsSphereAndTriangle(sphere, vertex1, vertex2, vertex3))
	            return ContainmentType.Intersects;
	        return ContainmentType.Disjoint;
	    }
	    static sphereContainsBox(sphere, box) {
	        var sphereC = sphere.center;
	        var sphereCeX = sphereC.x;
	        var sphereCeY = sphereC.y;
	        var sphereCeZ = sphereC.z;
	        var sphereR = sphere.radius;
	        var boxMin = box.min;
	        var boxMineX = boxMin.x;
	        var boxMineY = boxMin.y;
	        var boxMineZ = boxMin.z;
	        var boxMax = box.max;
	        var boxMaxeX = boxMax.x;
	        var boxMaxeY = boxMax.y;
	        var boxMaxeZ = boxMax.z;
	        var _tempV30e = CollisionUtils._tempV30;
	        var _tempV30eX = _tempV30e.x;
	        var _tempV30eY = _tempV30e.y;
	        var _tempV30eZ = _tempV30e.z;
	        if (!CollisionUtils.intersectsBoxAndSphere(box, sphere))
	            return ContainmentType.Disjoint;
	        var radiusSquared = sphereR * sphereR;
	        _tempV30eX = sphereCeX - boxMineX;
	        _tempV30eY = sphereCeY - boxMaxeY;
	        _tempV30eZ = sphereCeZ - boxMaxeZ;
	        if (Vector3.scalarLengthSquared(CollisionUtils._tempV30) > radiusSquared)
	            return ContainmentType.Intersects;
	        _tempV30eX = sphereCeX - boxMaxeX;
	        _tempV30eY = sphereCeY - boxMaxeY;
	        _tempV30eZ = sphereCeZ - boxMaxeZ;
	        if (Vector3.scalarLengthSquared(CollisionUtils._tempV30) > radiusSquared)
	            return ContainmentType.Intersects;
	        _tempV30eX = sphereCeX - boxMaxeX;
	        _tempV30eY = sphereCeY - boxMineY;
	        _tempV30eZ = sphereCeZ - boxMaxeZ;
	        if (Vector3.scalarLengthSquared(CollisionUtils._tempV30) > radiusSquared)
	            return ContainmentType.Intersects;
	        _tempV30eX = sphereCeX - boxMineX;
	        _tempV30eY = sphereCeY - boxMineY;
	        _tempV30eZ = sphereCeZ - boxMaxeZ;
	        if (Vector3.scalarLengthSquared(CollisionUtils._tempV30) > radiusSquared)
	            return ContainmentType.Intersects;
	        _tempV30eX = sphereCeX - boxMineX;
	        _tempV30eY = sphereCeY - boxMaxeY;
	        _tempV30eZ = sphereCeZ - boxMineZ;
	        if (Vector3.scalarLengthSquared(CollisionUtils._tempV30) > radiusSquared)
	            return ContainmentType.Intersects;
	        _tempV30eX = sphereCeX - boxMaxeX;
	        _tempV30eY = sphereCeY - boxMaxeY;
	        _tempV30eZ = sphereCeZ - boxMineZ;
	        if (Vector3.scalarLengthSquared(CollisionUtils._tempV30) > radiusSquared)
	            return ContainmentType.Intersects;
	        _tempV30eX = sphereCeX - boxMaxeX;
	        _tempV30eY = sphereCeY - boxMineY;
	        _tempV30eZ = sphereCeZ - boxMineZ;
	        if (Vector3.scalarLengthSquared(CollisionUtils._tempV30) > radiusSquared)
	            return ContainmentType.Intersects;
	        _tempV30eX = sphereCeX - boxMineX;
	        _tempV30eY = sphereCeY - boxMineY;
	        _tempV30eZ = sphereCeZ - boxMineZ;
	        if (Vector3.scalarLengthSquared(CollisionUtils._tempV30) > radiusSquared)
	            return ContainmentType.Intersects;
	        return ContainmentType.Contains;
	    }
	    static sphereContainsSphere(sphere1, sphere2) {
	        var sphere1R = sphere1.radius;
	        var sphere2R = sphere2.radius;
	        var distance = Vector3.distance(sphere1.center, sphere2.center);
	        if (sphere1R + sphere2R < distance)
	            return ContainmentType.Disjoint;
	        if (sphere1R - sphere2R < distance)
	            return ContainmentType.Intersects;
	        return ContainmentType.Contains;
	    }
	    static closestPointPointTriangle(point, vertex1, vertex2, vertex3, out) {
	        Vector3.subtract(vertex2, vertex1, CollisionUtils._tempV30);
	        Vector3.subtract(vertex3, vertex1, CollisionUtils._tempV31);
	        Vector3.subtract(point, vertex1, CollisionUtils._tempV32);
	        Vector3.subtract(point, vertex2, CollisionUtils._tempV33);
	        Vector3.subtract(point, vertex3, CollisionUtils._tempV34);
	        var d1 = Vector3.dot(CollisionUtils._tempV30, CollisionUtils._tempV32);
	        var d2 = Vector3.dot(CollisionUtils._tempV31, CollisionUtils._tempV32);
	        var d3 = Vector3.dot(CollisionUtils._tempV30, CollisionUtils._tempV33);
	        var d4 = Vector3.dot(CollisionUtils._tempV31, CollisionUtils._tempV33);
	        var d5 = Vector3.dot(CollisionUtils._tempV30, CollisionUtils._tempV34);
	        var d6 = Vector3.dot(CollisionUtils._tempV31, CollisionUtils._tempV34);
	        if (d1 <= 0 && d2 <= 0) {
	            vertex1.cloneTo(out);
	            return;
	        }
	        if (d3 >= 0 && d4 <= d3) {
	            vertex2.cloneTo(out);
	            return;
	        }
	        var vc = d1 * d4 - d3 * d2;
	        if (vc <= 0 && d1 >= 0 && d3 <= 0) {
	            var v = d1 / (d1 - d3);
	            Vector3.scale(CollisionUtils._tempV30, v, out);
	            Vector3.add(vertex1, out, out);
	            return;
	        }
	        if (d6 >= 0 && d5 <= d6) {
	            vertex3.cloneTo(out);
	            return;
	        }
	        var vb = d5 * d2 - d1 * d6;
	        if (vb <= 0 && d2 >= 0 && d6 <= 0) {
	            var w = d2 / (d2 - d6);
	            Vector3.scale(CollisionUtils._tempV31, w, out);
	            Vector3.add(vertex1, out, out);
	            return;
	        }
	        var va = d3 * d6 - d5 * d4;
	        if (va <= 0 && (d4 - d3) >= 0 && (d5 - d6) >= 0) {
	            var w3 = (d4 - d3) / ((d4 - d3) + (d5 - d6));
	            Vector3.subtract(vertex3, vertex2, out);
	            Vector3.scale(out, w3, out);
	            Vector3.add(vertex2, out, out);
	            return;
	        }
	        var denom = 1 / (va + vb + vc);
	        var v2 = vb * denom;
	        var w2 = vc * denom;
	        Vector3.scale(CollisionUtils._tempV30, v2, CollisionUtils._tempV35);
	        Vector3.scale(CollisionUtils._tempV31, w2, CollisionUtils._tempV36);
	        Vector3.add(CollisionUtils._tempV35, CollisionUtils._tempV36, out);
	        Vector3.add(vertex1, out, out);
	    }
	    static closestPointPlanePoint(plane, point, out) {
	        var planeN = plane.normal;
	        var t = Vector3.dot(planeN, point) - plane.distance;
	        Vector3.scale(planeN, t, CollisionUtils._tempV30);
	        Vector3.subtract(point, CollisionUtils._tempV30, out);
	    }
	    static closestPointBoxPoint(box, point, out) {
	        Vector3.max(point, box.min, CollisionUtils._tempV30);
	        Vector3.min(CollisionUtils._tempV30, box.max, out);
	    }
	    static closestPointSpherePoint(sphere, point, out) {
	        var sphereC = sphere.center;
	        Vector3.subtract(point, sphereC, out);
	        Vector3.normalize(out, out);
	        Vector3.scale(out, sphere.radius, out);
	        Vector3.add(out, sphereC, out);
	    }
	    static closestPointSphereSphere(sphere1, sphere2, out) {
	        var sphere1C = sphere1.center;
	        Vector3.subtract(sphere2.center, sphere1C, out);
	        Vector3.normalize(out, out);
	        Vector3.scale(out, sphere1.radius, out);
	        Vector3.add(out, sphere1C, out);
	    }
	}
	CollisionUtils._tempV30 = new Vector3();
	CollisionUtils._tempV31 = new Vector3();
	CollisionUtils._tempV32 = new Vector3();
	CollisionUtils._tempV33 = new Vector3();
	CollisionUtils._tempV34 = new Vector3();
	CollisionUtils._tempV35 = new Vector3();
	CollisionUtils._tempV36 = new Vector3();

	class BoundFrustum {
	    constructor(matrix) {
	        this._matrix = matrix;
	        this._near = new Plane(new Vector3());
	        this._far = new Plane(new Vector3());
	        this._left = new Plane(new Vector3());
	        this._right = new Plane(new Vector3());
	        this._top = new Plane(new Vector3());
	        this._bottom = new Plane(new Vector3());
	        BoundFrustum._getPlanesFromMatrix(this._matrix, this._near, this._far, this._left, this._right, this._top, this._bottom);
	    }
	    get matrix() {
	        return this._matrix;
	    }
	    set matrix(matrix) {
	        this._matrix = matrix;
	        BoundFrustum._getPlanesFromMatrix(this._matrix, this._near, this._far, this._left, this._right, this._top, this._bottom);
	    }
	    get near() {
	        return this._near;
	    }
	    get far() {
	        return this._far;
	    }
	    get left() {
	        return this._left;
	    }
	    get right() {
	        return this._right;
	    }
	    get top() {
	        return this._top;
	    }
	    get bottom() {
	        return this._bottom;
	    }
	    equalsBoundFrustum(other) {
	        return this._matrix.equalsOtherMatrix(other.matrix);
	    }
	    equalsObj(obj) {
	        if (obj instanceof BoundFrustum) {
	            var bf = obj;
	            return this.equalsBoundFrustum(bf);
	        }
	        return false;
	    }
	    getPlane(index) {
	        switch (index) {
	            case 0:
	                return this._near;
	            case 1:
	                return this._far;
	            case 2:
	                return this._left;
	            case 3:
	                return this._right;
	            case 4:
	                return this._top;
	            case 5:
	                return this._bottom;
	            default:
	                return null;
	        }
	    }
	    static _getPlanesFromMatrix(m, np, fp, lp, rp, tp, bp) {
	        var matrixE = m.elements;
	        var m11 = matrixE[0];
	        var m12 = matrixE[1];
	        var m13 = matrixE[2];
	        var m14 = matrixE[3];
	        var m21 = matrixE[4];
	        var m22 = matrixE[5];
	        var m23 = matrixE[6];
	        var m24 = matrixE[7];
	        var m31 = matrixE[8];
	        var m32 = matrixE[9];
	        var m33 = matrixE[10];
	        var m34 = matrixE[11];
	        var m41 = matrixE[12];
	        var m42 = matrixE[13];
	        var m43 = matrixE[14];
	        var m44 = matrixE[15];
	        var nearNorE = np.normal;
	        nearNorE.x = m14 + m13;
	        nearNorE.y = m24 + m23;
	        nearNorE.z = m34 + m33;
	        np.distance = m44 + m43;
	        np.normalize();
	        var farNorE = fp.normal;
	        farNorE.x = m14 - m13;
	        farNorE.y = m24 - m23;
	        farNorE.z = m34 - m33;
	        fp.distance = m44 - m43;
	        fp.normalize();
	        var leftNorE = lp.normal;
	        leftNorE.x = m14 + m11;
	        leftNorE.y = m24 + m21;
	        leftNorE.z = m34 + m31;
	        lp.distance = m44 + m41;
	        lp.normalize();
	        var rightNorE = rp.normal;
	        rightNorE.x = m14 - m11;
	        rightNorE.y = m24 - m21;
	        rightNorE.z = m34 - m31;
	        rp.distance = m44 - m41;
	        rp.normalize();
	        var topNorE = tp.normal;
	        topNorE.x = m14 - m12;
	        topNorE.y = m24 - m22;
	        topNorE.z = m34 - m32;
	        tp.distance = m44 - m42;
	        tp.normalize();
	        var bottomNorE = bp.normal;
	        bottomNorE.x = m14 + m12;
	        bottomNorE.y = m24 + m22;
	        bottomNorE.z = m34 + m32;
	        bp.distance = m44 + m42;
	        bp.normalize();
	    }
	    static _get3PlaneInterPoint(p1, p2, p3) {
	        var p1Nor = p1.normal;
	        var p2Nor = p2.normal;
	        var p3Nor = p3.normal;
	        Vector3.cross(p2Nor, p3Nor, BoundFrustum._tempV30);
	        Vector3.cross(p3Nor, p1Nor, BoundFrustum._tempV31);
	        Vector3.cross(p1Nor, p2Nor, BoundFrustum._tempV32);
	        var a = Vector3.dot(p1Nor, BoundFrustum._tempV30);
	        var b = Vector3.dot(p2Nor, BoundFrustum._tempV31);
	        var c = Vector3.dot(p3Nor, BoundFrustum._tempV32);
	        Vector3.scale(BoundFrustum._tempV30, -p1.distance / a, BoundFrustum._tempV33);
	        Vector3.scale(BoundFrustum._tempV31, -p2.distance / b, BoundFrustum._tempV34);
	        Vector3.scale(BoundFrustum._tempV32, -p3.distance / c, BoundFrustum._tempV35);
	        Vector3.add(BoundFrustum._tempV33, BoundFrustum._tempV34, BoundFrustum._tempV36);
	        Vector3.add(BoundFrustum._tempV35, BoundFrustum._tempV36, BoundFrustum._tempV37);
	        var v = BoundFrustum._tempV37;
	        return v;
	    }
	    getCorners(corners) {
	        BoundFrustum._get3PlaneInterPoint(this._near, this._bottom, this._right).cloneTo(corners[0]);
	        BoundFrustum._get3PlaneInterPoint(this._near, this._top, this._right).cloneTo(corners[1]);
	        BoundFrustum._get3PlaneInterPoint(this._near, this._top, this._left).cloneTo(corners[2]);
	        BoundFrustum._get3PlaneInterPoint(this._near, this._bottom, this._left).cloneTo(corners[3]);
	        BoundFrustum._get3PlaneInterPoint(this._far, this._bottom, this._right).cloneTo(corners[4]);
	        BoundFrustum._get3PlaneInterPoint(this._far, this._top, this._right).cloneTo(corners[5]);
	        BoundFrustum._get3PlaneInterPoint(this._far, this._top, this._left).cloneTo(corners[6]);
	        BoundFrustum._get3PlaneInterPoint(this._far, this._bottom, this._left).cloneTo(corners[7]);
	    }
	    containsPoint(point) {
	        var result = Plane.PlaneIntersectionType_Front;
	        var planeResult = Plane.PlaneIntersectionType_Front;
	        for (var i = 0; i < 6; i++) {
	            switch (i) {
	                case 0:
	                    planeResult = CollisionUtils.intersectsPlaneAndPoint(this._near, point);
	                    break;
	                case 1:
	                    planeResult = CollisionUtils.intersectsPlaneAndPoint(this._far, point);
	                    break;
	                case 2:
	                    planeResult = CollisionUtils.intersectsPlaneAndPoint(this._left, point);
	                    break;
	                case 3:
	                    planeResult = CollisionUtils.intersectsPlaneAndPoint(this._right, point);
	                    break;
	                case 4:
	                    planeResult = CollisionUtils.intersectsPlaneAndPoint(this._top, point);
	                    break;
	                case 5:
	                    planeResult = CollisionUtils.intersectsPlaneAndPoint(this._bottom, point);
	                    break;
	            }
	            switch (planeResult) {
	                case Plane.PlaneIntersectionType_Back:
	                    return ContainmentType.Disjoint;
	                case Plane.PlaneIntersectionType_Intersecting:
	                    result = Plane.PlaneIntersectionType_Intersecting;
	                    break;
	            }
	        }
	        switch (result) {
	            case Plane.PlaneIntersectionType_Intersecting:
	                return ContainmentType.Intersects;
	            default:
	                return ContainmentType.Contains;
	        }
	    }
	    intersects(box) {
	        var min = box.min;
	        var max = box.max;
	        var minX = min.x;
	        var minY = min.y;
	        var minZ = min.z;
	        var maxX = max.x;
	        var maxY = max.y;
	        var maxZ = max.z;
	        var nearNormal = this._near.normal;
	        if (this._near.distance + (nearNormal.x * (nearNormal.x < 0 ? minX : maxX)) + (nearNormal.y * (nearNormal.y < 0 ? minY : maxY)) + (nearNormal.z * (nearNormal.z < 0 ? minZ : maxZ)) < 0)
	            return false;
	        var leftNormal = this._left.normal;
	        if (this._left.distance + (leftNormal.x * (leftNormal.x < 0 ? minX : maxX)) + (leftNormal.y * (leftNormal.y < 0 ? minY : maxY)) + (leftNormal.z * (leftNormal.z < 0 ? minZ : maxZ)) < 0)
	            return false;
	        var rightNormal = this._right.normal;
	        if (this._right.distance + (rightNormal.x * (rightNormal.x < 0 ? minX : maxX)) + (rightNormal.y * (rightNormal.y < 0 ? minY : maxY)) + (rightNormal.z * (rightNormal.z < 0 ? minZ : maxZ)) < 0)
	            return false;
	        var bottomNormal = this._bottom.normal;
	        if (this._bottom.distance + (bottomNormal.x * (bottomNormal.x < 0 ? minX : maxX)) + (bottomNormal.y * (bottomNormal.y < 0 ? minY : maxY)) + (bottomNormal.z * (bottomNormal.z < 0 ? minZ : maxZ)) < 0)
	            return false;
	        var topNormal = this._top.normal;
	        if (this._top.distance + (topNormal.x * (topNormal.x < 0 ? minX : maxX)) + (topNormal.y * (topNormal.y < 0 ? minY : maxY)) + (topNormal.z * (topNormal.z < 0 ? minZ : maxZ)) < 0)
	            return false;
	        var farNormal = this._far.normal;
	        if (this._far.distance + (farNormal.x * (farNormal.x < 0 ? minX : maxX)) + (farNormal.y * (farNormal.y < 0 ? minY : maxY)) + (farNormal.z * (farNormal.z < 0 ? minZ : maxZ)) < 0)
	            return false;
	        return true;
	    }
	    containsBoundBox(box) {
	        var p = BoundFrustum._tempV30, n = BoundFrustum._tempV31;
	        var boxMin = box.min;
	        var boxMax = box.max;
	        var result = ContainmentType.Contains;
	        for (var i = 0; i < 6; i++) {
	            var plane = this.getPlane(i);
	            var planeNor = plane.normal;
	            if (planeNor.x >= 0) {
	                p.x = boxMax.x;
	                n.x = boxMin.x;
	            }
	            else {
	                p.x = boxMin.x;
	                n.x = boxMax.x;
	            }
	            if (planeNor.y >= 0) {
	                p.y = boxMax.y;
	                n.y = boxMin.y;
	            }
	            else {
	                p.y = boxMin.y;
	                n.y = boxMax.y;
	            }
	            if (planeNor.z >= 0) {
	                p.z = boxMax.z;
	                n.z = boxMin.z;
	            }
	            else {
	                p.z = boxMin.z;
	                n.z = boxMax.z;
	            }
	            if (CollisionUtils.intersectsPlaneAndPoint(plane, p) === Plane.PlaneIntersectionType_Back)
	                return ContainmentType.Disjoint;
	            if (CollisionUtils.intersectsPlaneAndPoint(plane, n) === Plane.PlaneIntersectionType_Back)
	                result = ContainmentType.Intersects;
	        }
	        return result;
	    }
	    containsBoundSphere(sphere) {
	        var result = Plane.PlaneIntersectionType_Front;
	        var planeResult = Plane.PlaneIntersectionType_Front;
	        for (var i = 0; i < 6; i++) {
	            switch (i) {
	                case 0:
	                    planeResult = CollisionUtils.intersectsPlaneAndSphere(this._near, sphere);
	                    break;
	                case 1:
	                    planeResult = CollisionUtils.intersectsPlaneAndSphere(this._far, sphere);
	                    break;
	                case 2:
	                    planeResult = CollisionUtils.intersectsPlaneAndSphere(this._left, sphere);
	                    break;
	                case 3:
	                    planeResult = CollisionUtils.intersectsPlaneAndSphere(this._right, sphere);
	                    break;
	                case 4:
	                    planeResult = CollisionUtils.intersectsPlaneAndSphere(this._top, sphere);
	                    break;
	                case 5:
	                    planeResult = CollisionUtils.intersectsPlaneAndSphere(this._bottom, sphere);
	                    break;
	            }
	            switch (planeResult) {
	                case Plane.PlaneIntersectionType_Back:
	                    return ContainmentType.Disjoint;
	                case Plane.PlaneIntersectionType_Intersecting:
	                    result = Plane.PlaneIntersectionType_Intersecting;
	                    break;
	            }
	        }
	        switch (result) {
	            case Plane.PlaneIntersectionType_Intersecting:
	                return ContainmentType.Intersects;
	            default:
	                return ContainmentType.Contains;
	        }
	    }
	}
	BoundFrustum._tempV30 = new Vector3();
	BoundFrustum._tempV31 = new Vector3();
	BoundFrustum._tempV32 = new Vector3();
	BoundFrustum._tempV33 = new Vector3();
	BoundFrustum._tempV34 = new Vector3();
	BoundFrustum._tempV35 = new Vector3();
	BoundFrustum._tempV36 = new Vector3();
	BoundFrustum._tempV37 = new Vector3();

	class Viewport {
	    constructor(x, y, width, height) {
	        this.minDepth = 0.0;
	        this.maxDepth = 1.0;
	        this.x = x;
	        this.y = y;
	        this.width = width;
	        this.height = height;
	    }
	    project(source, matrix, out) {
	        var sX = source.x;
	        var sY = source.y;
	        var sZ = source.z;
	        Vector3.transformV3ToV3(source, matrix, out);
	        var matE = matrix.elements;
	        var a = (((sX * matE[3]) + (sY * matE[7])) + (sZ * matE[11])) + matE[15];
	        if (a !== 1.0) {
	            out.x = out.x / a;
	            out.y = out.y / a;
	            out.z = out.z / a;
	        }
	        out.x = (((out.x + 1.0) * 0.5) * this.width) + this.x;
	        out.y = (((-out.y + 1.0) * 0.5) * this.height) + this.y;
	        out.z = (out.z * (this.maxDepth - this.minDepth)) + this.minDepth;
	    }
	    unprojectFromMat(source, matrix, out) {
	        var matrixEleme = matrix.elements;
	        out.x = (((source.x - this.x) / (this.width)) * 2.0) - 1.0;
	        out.y = -((((source.y - this.y) / (this.height)) * 2.0) - 1.0);
	        var halfDepth = (this.maxDepth - this.minDepth) / 2;
	        out.z = (source.z - this.minDepth - halfDepth) / halfDepth;
	        var a = (((out.x * matrixEleme[3]) + (out.y * matrixEleme[7])) + (out.z * matrixEleme[11])) + matrixEleme[15];
	        Vector3.transformV3ToV3(out, matrix, out);
	        if (a !== 1.0) {
	            out.x = out.x / a;
	            out.y = out.y / a;
	            out.z = out.z / a;
	        }
	    }
	    unprojectFromWVP(source, projection, view, world, out) {
	        Matrix4x4.multiply(projection, view, Viewport._tempMatrix4x4);
	        (world) && (Matrix4x4.multiply(Viewport._tempMatrix4x4, world, Viewport._tempMatrix4x4));
	        Viewport._tempMatrix4x4.invert(Viewport._tempMatrix4x4);
	        this.unprojectFromMat(source, Viewport._tempMatrix4x4, out);
	    }
	    cloneTo(out) {
	        out.x = this.x;
	        out.y = this.y;
	        out.width = this.width;
	        out.height = this.height;
	        out.minDepth = this.minDepth;
	        out.maxDepth = this.maxDepth;
	    }
	}
	Viewport._tempMatrix4x4 = new Matrix4x4();

	class Picker {
	    constructor() {
	    }
	    static calculateCursorRay(point, viewPort, projectionMatrix, viewMatrix, world, out) {
	        var x = point.x;
	        var y = point.y;
	        var nearSource = Picker._tempVector30;
	        var nerSourceE = nearSource;
	        nerSourceE.x = x;
	        nerSourceE.y = y;
	        nerSourceE.z = viewPort.minDepth;
	        var farSource = Picker._tempVector31;
	        var farSourceE = farSource;
	        farSourceE.x = x;
	        farSourceE.y = y;
	        farSourceE.z = viewPort.maxDepth;
	        var nearPoint = out.origin;
	        var farPoint = Picker._tempVector32;
	        viewPort.unprojectFromWVP(nearSource, projectionMatrix, viewMatrix, world, nearPoint);
	        viewPort.unprojectFromWVP(farSource, projectionMatrix, viewMatrix, world, farPoint);
	        var outDire = out.direction;
	        outDire.x = farPoint.x - nearPoint.x;
	        outDire.y = farPoint.y - nearPoint.y;
	        outDire.z = farPoint.z - nearPoint.z;
	        Vector3.normalize(out.direction, out.direction);
	    }
	    static rayIntersectsTriangle(ray, vertex1, vertex2, vertex3) {
	        var result;
	        var edge1 = Picker._tempVector30, edge2 = Picker._tempVector31;
	        Vector3.subtract(vertex2, vertex1, edge1);
	        Vector3.subtract(vertex3, vertex1, edge2);
	        var directionCrossEdge2 = Picker._tempVector32;
	        Vector3.cross(ray.direction, edge2, directionCrossEdge2);
	        var determinant;
	        determinant = Vector3.dot(edge1, directionCrossEdge2);
	        if (determinant > -Number.MIN_VALUE && determinant < Number.MIN_VALUE) {
	            result = Number.NaN;
	            return result;
	        }
	        var inverseDeterminant = 1.0 / determinant;
	        var distanceVector = Picker._tempVector33;
	        Vector3.subtract(ray.origin, vertex1, distanceVector);
	        var triangleU;
	        triangleU = Vector3.dot(distanceVector, directionCrossEdge2);
	        triangleU *= inverseDeterminant;
	        if (triangleU < 0 || triangleU > 1) {
	            result = Number.NaN;
	            return result;
	        }
	        var distanceCrossEdge1 = Picker._tempVector34;
	        Vector3.cross(distanceVector, edge1, distanceCrossEdge1);
	        var triangleV;
	        triangleV = Vector3.dot(ray.direction, distanceCrossEdge1);
	        triangleV *= inverseDeterminant;
	        if (triangleV < 0 || triangleU + triangleV > 1) {
	            result = Number.NaN;
	            return result;
	        }
	        var rayDistance;
	        rayDistance = Vector3.dot(edge2, distanceCrossEdge1);
	        rayDistance *= inverseDeterminant;
	        if (rayDistance < 0) {
	            result = Number.NaN;
	            return result;
	        }
	        result = rayDistance;
	        return result;
	    }
	}
	Picker._tempVector30 = new Vector3();
	Picker._tempVector31 = new Vector3();
	Picker._tempVector32 = new Vector3();
	Picker._tempVector33 = new Vector3();
	Picker._tempVector34 = new Vector3();

	class SystemUtils {
	    static supportTextureFormat(format) {
	        switch (format) {
	            case Laya.TextureFormat.R32G32B32A32:
	                if (!Laya.LayaGL.layaGPUInstance._isWebGL2 && !Laya.LayaGL.layaGPUInstance._oesTextureFloat)
	                    return false;
	                else
	                    return true;
	            default:
	                return true;
	        }
	    }
	    static supportRenderTextureFormat(format) {
	        switch (format) {
	            case Laya.RenderTextureFormat.R16G16B16A16:
	                if (Laya.LayaGL.layaGPUInstance._isWebGL2 || Laya.LayaGL.layaGPUInstance._oesTextureHalfFloat && Laya.LayaGL.layaGPUInstance._oesTextureHalfFloatLinear)
	                    return true;
	                else
	                    return false;
	            default:
	                return true;
	        }
	    }
	}

	class BufferState extends Laya.BufferStateBase {
	    constructor() {
	        super();
	    }
	    applyVertexBuffer(vertexBuffer) {
	        if (Laya.BufferStateBase._curBindedBufferState === this) {
	            var gl = Laya.LayaGL.instance;
	            var verDec = vertexBuffer.vertexDeclaration;
	            var valueData = verDec._shaderValues.getData();
	            this.vertexDeclaration = verDec;
	            vertexBuffer.bind();
	            for (var k in valueData) {
	                var loc = parseInt(k);
	                var attribute = valueData[k];
	                gl.enableVertexAttribArray(loc);
	                gl.vertexAttribPointer(loc, attribute[0], attribute[1], !!attribute[2], attribute[3], attribute[4]);
	            }
	        }
	        else {
	            throw "BufferState: must call bind() function first.";
	        }
	    }
	    applyVertexBuffers(vertexBuffers) {
	        if (Laya.BufferStateBase._curBindedBufferState === this) {
	            var gl = Laya.LayaGL.instance;
	            for (var i = 0, n = vertexBuffers.length; i < n; i++) {
	                var verBuf = vertexBuffers[i];
	                var verDec = verBuf.vertexDeclaration;
	                var valueData = verDec._shaderValues.getData();
	                verBuf.bind();
	                for (var k in valueData) {
	                    var loc = parseInt(k);
	                    var attribute = valueData[k];
	                    gl.enableVertexAttribArray(loc);
	                    gl.vertexAttribPointer(loc, attribute[0], attribute[1], !!attribute[2], attribute[3], attribute[4]);
	                }
	            }
	        }
	        else {
	            throw "BufferState: must call bind() function first.";
	        }
	    }
	    applyInstanceVertexBuffer(vertexBuffer) {
	        if (Laya.LayaGL.layaGPUInstance.supportInstance()) {
	            if (Laya.BufferStateBase._curBindedBufferState === this) {
	                var gl = Laya.LayaGL.instance;
	                var verDec = vertexBuffer.vertexDeclaration;
	                var valueData = verDec._shaderValues.getData();
	                vertexBuffer.bind();
	                for (var k in valueData) {
	                    var loc = parseInt(k);
	                    var attribute = valueData[k];
	                    gl.enableVertexAttribArray(loc);
	                    gl.vertexAttribPointer(loc, attribute[0], attribute[1], !!attribute[2], attribute[3], attribute[4]);
	                    Laya.LayaGL.layaGPUInstance.vertexAttribDivisor(loc, 1);
	                }
	            }
	            else {
	                throw "BufferState: must call bind() function first.";
	            }
	        }
	    }
	    applyIndexBuffer(indexBuffer) {
	        if (Laya.BufferStateBase._curBindedBufferState === this) {
	            if (this._bindedIndexBuffer !== indexBuffer) {
	                indexBuffer._bindForVAO();
	                this._bindedIndexBuffer = indexBuffer;
	            }
	        }
	        else {
	            throw "BufferState: must call bind() function first.";
	        }
	    }
	}

	class IndexBuffer3D extends Laya.Buffer {
	    constructor(indexType, indexCount, bufferUsage = 0x88E4, canRead = false) {
	        super();
	        this._indexType = indexType;
	        this._indexCount = indexCount;
	        this._bufferUsage = bufferUsage;
	        this._bufferType = Laya.LayaGL.instance.ELEMENT_ARRAY_BUFFER;
	        this._canRead = canRead;
	        var byteLength;
	        if (indexType == IndexBuffer3D.INDEXTYPE_USHORT)
	            this._indexTypeByteCount = 2;
	        else if (indexType == IndexBuffer3D.INDEXTYPE_UBYTE)
	            this._indexTypeByteCount = 1;
	        else
	            throw new Error("unidentification index type.");
	        byteLength = this._indexTypeByteCount * indexCount;
	        this._byteLength = byteLength;
	        var curBufSta = Laya.BufferStateBase._curBindedBufferState;
	        if (curBufSta) {
	            if (curBufSta._bindedIndexBuffer === this) {
	                Laya.LayaGL.instance.bufferData(this._bufferType, byteLength, this._bufferUsage);
	            }
	            else {
	                curBufSta.unBind();
	                this.bind();
	                Laya.LayaGL.instance.bufferData(this._bufferType, byteLength, this._bufferUsage);
	                curBufSta.bind();
	            }
	        }
	        else {
	            this.bind();
	            Laya.LayaGL.instance.bufferData(this._bufferType, byteLength, this._bufferUsage);
	        }
	        if (canRead) {
	            if (indexType == IndexBuffer3D.INDEXTYPE_USHORT)
	                this._buffer = new Uint16Array(indexCount);
	            else if (indexType == IndexBuffer3D.INDEXTYPE_UBYTE)
	                this._buffer = new Uint8Array(indexCount);
	        }
	    }
	    get indexType() {
	        return this._indexType;
	    }
	    get indexTypeByteCount() {
	        return this._indexTypeByteCount;
	    }
	    get indexCount() {
	        return this._indexCount;
	    }
	    get canRead() {
	        return this._canRead;
	    }
	    _bindForVAO() {
	        if (Laya.BufferStateBase._curBindedBufferState) {
	            var gl = Laya.LayaGL.instance;
	            gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._glBuffer);
	        }
	        else {
	            throw "IndexBuffer3D: must bind current BufferState.";
	        }
	    }
	    bind() {
	        if (Laya.BufferStateBase._curBindedBufferState) {
	            throw "IndexBuffer3D: must unbind current BufferState.";
	        }
	        else {
	            if (Laya.Buffer._bindedIndexBuffer !== this._glBuffer) {
	                var gl = Laya.LayaGL.instance;
	                gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._glBuffer);
	                Laya.Buffer._bindedIndexBuffer = this._glBuffer;
	                return true;
	            }
	            else {
	                return false;
	            }
	        }
	    }
	    setData(data, bufferOffset = 0, dataStartIndex = 0, dataCount = 4294967295) {
	        var byteCount;
	        if (this._indexType == IndexBuffer3D.INDEXTYPE_USHORT) {
	            byteCount = 2;
	            if (dataStartIndex !== 0 || dataCount !== 4294967295)
	                data = new Uint16Array(data.buffer, dataStartIndex * byteCount, dataCount);
	        }
	        else if (this._indexType == IndexBuffer3D.INDEXTYPE_UBYTE) {
	            byteCount = 1;
	            if (dataStartIndex !== 0 || dataCount !== 4294967295)
	                data = new Uint8Array(data.buffer, dataStartIndex * byteCount, dataCount);
	        }
	        var curBufSta = Laya.BufferStateBase._curBindedBufferState;
	        if (curBufSta) {
	            if (curBufSta._bindedIndexBuffer === this) {
	                Laya.LayaGL.instance.bufferSubData(this._bufferType, bufferOffset * byteCount, data);
	            }
	            else {
	                curBufSta.unBind();
	                this.bind();
	                Laya.LayaGL.instance.bufferSubData(this._bufferType, bufferOffset * byteCount, data);
	                curBufSta.bind();
	            }
	        }
	        else {
	            this.bind();
	            Laya.LayaGL.instance.bufferSubData(this._bufferType, bufferOffset * byteCount, data);
	        }
	        if (this._canRead) {
	            if (bufferOffset !== 0 || dataStartIndex !== 0 || dataCount !== 4294967295) {
	                var maxLength = this._buffer.length - bufferOffset;
	                if (dataCount > maxLength)
	                    dataCount = maxLength;
	                for (var i = 0; i < dataCount; i++)
	                    this._buffer[bufferOffset + i] = data[i];
	            }
	            else {
	                this._buffer = data;
	            }
	        }
	    }
	    getData() {
	        if (this._canRead)
	            return this._buffer;
	        else
	            throw new Error("Can't read data from VertexBuffer with only write flag!");
	    }
	    destroy() {
	        super.destroy();
	        this._buffer = null;
	    }
	}
	IndexBuffer3D.INDEXTYPE_UBYTE = "ubyte";
	IndexBuffer3D.INDEXTYPE_USHORT = "ushort";

	class SkyMesh {
	    constructor() {
	    }
	    _render(state) {
	    }
	}

	class SkyBox extends SkyMesh {
	    static __init__() {
	        SkyBox.instance = new SkyBox();
	    }
	    constructor() {
	        super();
	        var gl = Laya.LayaGL.instance;
	        var halfHeight = 1.0;
	        var halfWidth = 1.0;
	        var halfDepth = 1.0;
	        var vertices = new Float32Array([-halfDepth, halfHeight, -halfWidth, halfDepth, halfHeight, -halfWidth, halfDepth, halfHeight, halfWidth, -halfDepth, halfHeight, halfWidth,
	            -halfDepth, -halfHeight, -halfWidth, halfDepth, -halfHeight, -halfWidth, halfDepth, -halfHeight, halfWidth, -halfDepth, -halfHeight, halfWidth]);
	        var indices = new Uint8Array([
	            0, 1, 2, 2, 3, 0,
	            4, 7, 6, 6, 5, 4,
	            0, 3, 7, 7, 4, 0,
	            1, 5, 6, 6, 2, 1,
	            3, 2, 6, 6, 7, 3,
	            0, 4, 5, 5, 1, 0
	        ]);
	        var verDec = VertexMesh.getVertexDeclaration("POSITION");
	        this._vertexBuffer = new VertexBuffer3D(verDec.vertexStride * 8, gl.STATIC_DRAW, false);
	        this._vertexBuffer.vertexDeclaration = verDec;
	        this._indexBuffer = new IndexBuffer3D(IndexBuffer3D.INDEXTYPE_UBYTE, 36, gl.STATIC_DRAW, false);
	        this._vertexBuffer.setData(vertices.buffer);
	        this._indexBuffer.setData(indices);
	        var bufferState = new BufferState();
	        bufferState.bind();
	        bufferState.applyVertexBuffer(this._vertexBuffer);
	        bufferState.applyIndexBuffer(this._indexBuffer);
	        bufferState.unBind();
	        this._bufferState = bufferState;
	    }
	    _render(state) {
	        var gl = Laya.LayaGL.instance;
	        gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_BYTE, 0);
	        Laya.Stat.trianglesFaces += 12;
	        Laya.Stat.renderBatches++;
	    }
	}

	class SkyRenderer {
	    constructor() {
	        this._mesh = SkyBox.instance;
	    }
	    get material() {
	        return this._material;
	    }
	    set material(value) {
	        if (this._material !== value) {
	            (this._material) && (this._material._removeReference());
	            (value) && (value._addReference());
	            this._material = value;
	        }
	    }
	    get mesh() {
	        return this._mesh;
	    }
	    set mesh(value) {
	        if (this._mesh !== value) {
	            this._mesh = value;
	        }
	    }
	    _isAvailable() {
	        return this._material && this._mesh ? true : false;
	    }
	    _render(state) {
	        if (this._material && this._mesh) {
	            var gl = Laya.LayaGL.instance;
	            var scene = state.scene;
	            var camera = state.camera;
	            var noteValue = ShaderData._SET_RUNTIME_VALUE_MODE_REFERENCE_;
	            Laya.ILaya.Render.supportWebGLPlusRendering && ShaderData.setRuntimeValueMode(false);
	            Laya.WebGLContext.setCullFace(gl, false);
	            Laya.WebGLContext.setDepthFunc(gl, gl.LEQUAL);
	            Laya.WebGLContext.setDepthMask(gl, false);
	            var comDef = SkyRenderer._compileDefine;
	            this._material._shaderValues._defineDatas.cloneTo(comDef);
	            var shader = state.shader = this._material._shader.getSubShaderAt(0)._passes[0].withCompile(comDef);
	            var switchShader = shader.bind();
	            var switchShaderLoop = (Laya.Stat.loopCount !== shader._uploadMark);
	            var uploadScene = (shader._uploadScene !== scene) || switchShaderLoop;
	            if (uploadScene || switchShader) {
	                shader.uploadUniforms(shader._sceneUniformParamsMap, scene._shaderValues, uploadScene);
	                shader._uploadScene = scene;
	            }
	            var renderTar = camera._getInternalRenderTexture();
	            var uploadCamera = (shader._uploadCamera !== camera) || switchShaderLoop;
	            if (uploadCamera || switchShader) {
	                var viewMatrix = SkyRenderer._tempMatrix0;
	                var projectionMatrix = SkyRenderer._tempMatrix1;
	                camera.viewMatrix.cloneTo(viewMatrix);
	                camera.projectionMatrix.cloneTo(projectionMatrix);
	                viewMatrix.setTranslationVector(Vector3._ZERO);
	                if (camera.orthographic)
	                    Matrix4x4.createPerspective(camera.fieldOfView, camera.aspectRatio, camera.nearPlane, camera.farPlane, projectionMatrix);
	                var epsilon = 1e-6;
	                var yScale = 1.0 / Math.tan(3.1416 * camera.fieldOfView / 180 * 0.5);
	                projectionMatrix.elements[0] = yScale / camera.aspectRatio;
	                projectionMatrix.elements[5] = yScale;
	                projectionMatrix.elements[10] = epsilon - 1.0;
	                projectionMatrix.elements[11] = -1.0;
	                projectionMatrix.elements[14] = -0;
	                camera._applyViewProject(state, viewMatrix, projectionMatrix, renderTar ? true : false);
	                shader.uploadUniforms(shader._cameraUniformParamsMap, camera._shaderValues, uploadCamera);
	                shader._uploadCamera = camera;
	            }
	            var uploadMaterial = (shader._uploadMaterial !== this._material) || switchShaderLoop;
	            if (uploadMaterial || switchShader) {
	                shader.uploadUniforms(shader._materialUniformParamsMap, this._material._shaderValues, uploadMaterial);
	                shader._uploadMaterial = this._material;
	            }
	            this._mesh._bufferState.bind();
	            this._mesh._render(state);
	            Laya.ILaya.Render.supportWebGLPlusRendering && ShaderData.setRuntimeValueMode(noteValue);
	            Laya.WebGLContext.setDepthFunc(gl, gl.LESS);
	            Laya.WebGLContext.setDepthMask(gl, true);
	            camera._applyViewProject(state, camera.viewMatrix, camera.projectionMatrix, renderTar ? true : false);
	        }
	    }
	    destroy() {
	        if (this._material) {
	            this._material._removeReference();
	            this._material = null;
	        }
	    }
	}
	SkyRenderer._tempMatrix0 = new Matrix4x4();
	SkyRenderer._tempMatrix1 = new Matrix4x4();
	SkyRenderer._compileDefine = new DefineDatas();

	class BaseCamera extends Sprite3D {
	    constructor(nearPlane = 0.3, farPlane = 1000) {
	        super();
	        this._skyRenderer = new SkyRenderer();
	        this._forward = new Vector3();
	        this._up = new Vector3();
	        this.clearColor = new Vector4(100 / 255, 149 / 255, 237 / 255, 255 / 255);
	        this._shaderValues = new ShaderData(null);
	        this._fieldOfView = 60;
	        this._useUserProjectionMatrix = false;
	        this._orthographic = false;
	        this._orthographicVerticalSize = 10;
	        this.renderingOrder = 0;
	        this._nearPlane = nearPlane;
	        this._farPlane = farPlane;
	        this.cullingMask = 2147483647;
	        this.clearFlag = BaseCamera.CLEARFLAG_SOLIDCOLOR;
	        this.useOcclusionCulling = true;
	    }
	    get skyRenderer() {
	        return this._skyRenderer;
	    }
	    get fieldOfView() {
	        return this._fieldOfView;
	    }
	    set fieldOfView(value) {
	        this._fieldOfView = value;
	        this._calculateProjectionMatrix();
	    }
	    get nearPlane() {
	        return this._nearPlane;
	    }
	    set nearPlane(value) {
	        this._nearPlane = value;
	        this._calculateProjectionMatrix();
	    }
	    get farPlane() {
	        return this._farPlane;
	    }
	    set farPlane(vaule) {
	        this._farPlane = vaule;
	        this._calculateProjectionMatrix();
	    }
	    get orthographic() {
	        return this._orthographic;
	    }
	    set orthographic(vaule) {
	        this._orthographic = vaule;
	        this._calculateProjectionMatrix();
	    }
	    get orthographicVerticalSize() {
	        return this._orthographicVerticalSize;
	    }
	    set orthographicVerticalSize(vaule) {
	        this._orthographicVerticalSize = vaule;
	        this._calculateProjectionMatrix();
	    }
	    get renderingOrder() {
	        return this._renderingOrder;
	    }
	    set renderingOrder(value) {
	        this._renderingOrder = value;
	        this._sortCamerasByRenderingOrder();
	    }
	    _sortCamerasByRenderingOrder() {
	        if (this.displayedInStage) {
	            var cameraPool = this.scene._cameraPool;
	            var n = cameraPool.length - 1;
	            for (var i = 0; i < n; i++) {
	                if (cameraPool[i].renderingOrder > cameraPool[n].renderingOrder) {
	                    var tempCamera = cameraPool[i];
	                    cameraPool[i] = cameraPool[n];
	                    cameraPool[n] = tempCamera;
	                }
	            }
	        }
	    }
	    _calculateProjectionMatrix() {
	    }
	    _onScreenSizeChanged() {
	        this._calculateProjectionMatrix();
	    }
	    _prepareCameraToRender() {
	        var cameraSV = this._shaderValues;
	        this.transform.getForward(this._forward);
	        this.transform.getUp(this._up);
	        cameraSV.setVector3(BaseCamera.CAMERAPOS, this.transform.position);
	        cameraSV.setVector3(BaseCamera.CAMERADIRECTION, this._forward);
	        cameraSV.setVector3(BaseCamera.CAMERAUP, this._up);
	    }
	    render(shader = null, replacementTag = null) {
	    }
	    addLayer(layer) {
	        this.cullingMask |= Math.pow(2, layer);
	    }
	    removeLayer(layer) {
	        this.cullingMask &= ~Math.pow(2, layer);
	    }
	    addAllLayers() {
	        this.cullingMask = 2147483647;
	    }
	    removeAllLayers() {
	        this.cullingMask = 0;
	    }
	    resetProjectionMatrix() {
	        this._useUserProjectionMatrix = false;
	        this._calculateProjectionMatrix();
	    }
	    _onActive() {
	        this._scene._addCamera(this);
	        super._onActive();
	    }
	    _onInActive() {
	        this._scene._removeCamera(this);
	        super._onInActive();
	    }
	    _parse(data, spriteMap) {
	        super._parse(data, spriteMap);
	        var clearFlagData = data.clearFlag;
	        (clearFlagData !== undefined) && (this.clearFlag = clearFlagData);
	        this.orthographic = data.orthographic;
	        (data.orthographicVerticalSize !== undefined) && (this.orthographicVerticalSize = data.orthographicVerticalSize);
	        (data.fieldOfView !== undefined) && (this.fieldOfView = data.fieldOfView);
	        this.nearPlane = data.nearPlane;
	        this.farPlane = data.farPlane;
	        var color = data.clearColor;
	        this.clearColor = new Vector4(color[0], color[1], color[2], color[3]);
	        var skyboxMaterial = data.skyboxMaterial;
	        if (skyboxMaterial) {
	            this._skyRenderer.material = Laya.Loader.getRes(skyboxMaterial.path);
	        }
	    }
	    destroy(destroyChild = true) {
	        this._skyRenderer.destroy();
	        this._skyRenderer = null;
	        Laya.Laya.stage.off(Laya.Event.RESIZE, this, this._onScreenSizeChanged);
	        super.destroy(destroyChild);
	    }
	    _create() {
	        return new BaseCamera();
	    }
	}
	BaseCamera._tempMatrix4x40 = new Matrix4x4();
	BaseCamera.CAMERAPOS = Shader3D.propertyNameToID("u_CameraPos");
	BaseCamera.VIEWMATRIX = Shader3D.propertyNameToID("u_View");
	BaseCamera.PROJECTMATRIX = Shader3D.propertyNameToID("u_Projection");
	BaseCamera.VIEWPROJECTMATRIX = Shader3D.propertyNameToID("u_ViewProjection");
	BaseCamera.CAMERADIRECTION = Shader3D.propertyNameToID("u_CameraDirection");
	BaseCamera.CAMERAUP = Shader3D.propertyNameToID("u_CameraUp");
	BaseCamera.VIEWPORT = Shader3D.propertyNameToID("u_Viewport");
	BaseCamera.PROJECTION_PARAMS = Shader3D.propertyNameToID("u_ProjectionParams");
	BaseCamera.RENDERINGTYPE_DEFERREDLIGHTING = "DEFERREDLIGHTING";
	BaseCamera.RENDERINGTYPE_FORWARDRENDERING = "FORWARDRENDERING";
	BaseCamera.CLEARFLAG_SOLIDCOLOR = 0;
	BaseCamera.CLEARFLAG_SKY = 1;
	BaseCamera.CLEARFLAG_DEPTHONLY = 2;
	BaseCamera.CLEARFLAG_NONE = 3;
	BaseCamera._invertYScaleMatrix = new Matrix4x4(1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
	BaseCamera._invertYProjectionMatrix = new Matrix4x4();
	BaseCamera._invertYProjectionViewMatrix = new Matrix4x4();

	class ScreenQuad extends Laya.Resource {
	    constructor() {
	        super();
	        this._bufferState = new BufferState();
	        this._bufferStateInvertUV = new BufferState();
	        var gl = Laya.LayaGL.instance;
	        this._vertexBuffer = new VertexBuffer3D(16 * 4, gl.STATIC_DRAW, false);
	        this._vertexBuffer.vertexDeclaration = ScreenQuad._vertexDeclaration;
	        this._vertexBuffer.setData(ScreenQuad._vertices.buffer);
	        this._bufferState.bind();
	        this._bufferState.applyVertexBuffer(this._vertexBuffer);
	        this._bufferState.unBind();
	        this._vertexBufferInvertUV = new VertexBuffer3D(16 * 4, gl.STATIC_DRAW, false);
	        this._vertexBufferInvertUV.vertexDeclaration = ScreenQuad._vertexDeclaration;
	        this._vertexBufferInvertUV.setData(ScreenQuad._verticesInvertUV.buffer);
	        this._bufferStateInvertUV.bind();
	        this._bufferStateInvertUV.applyVertexBuffer(this._vertexBufferInvertUV);
	        this._bufferStateInvertUV.unBind();
	        this._setGPUMemory(this._vertexBuffer._byteLength + this._vertexBufferInvertUV._byteLength);
	    }
	    static __init__() {
	        ScreenQuad._vertexDeclaration = new VertexDeclaration(16, [new VertexElement(0, VertexElementFormat.Vector4, ScreenQuad.SCREENQUAD_POSITION_UV)]);
	        ScreenQuad.instance = new ScreenQuad();
	        ScreenQuad.instance.lock = true;
	    }
	    render() {
	        var gl = Laya.LayaGL.instance;
	        this._bufferState.bind();
	        gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
	        Laya.Stat.renderBatches++;
	    }
	    renderInvertUV() {
	        var gl = Laya.LayaGL.instance;
	        this._bufferStateInvertUV.bind();
	        gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
	        Laya.Stat.renderBatches++;
	    }
	    destroy() {
	        super.destroy();
	        this._bufferState.destroy();
	        this._vertexBuffer.destroy();
	        this._bufferStateInvertUV.destroy();
	        this._vertexBufferInvertUV.destroy();
	        this._setGPUMemory(0);
	    }
	}
	ScreenQuad.SCREENQUAD_POSITION_UV = 0;
	ScreenQuad._vertices = new Float32Array([1, 1, 1, 0, 1, -1, 1, 1, -1, 1, 0, 0, -1, -1, 0, 1]);
	ScreenQuad._verticesInvertUV = new Float32Array([1, 1, 1, 1, 1, -1, 1, 0, -1, 1, 0, 1, -1, -1, 0, 0]);

	class ScreenTriangle extends Laya.Resource {
	    constructor() {
	        super();
	        this._bufferState = new BufferState();
	        this._bufferStateInvertUV = new BufferState();
	        var gl = Laya.LayaGL.instance;
	        this._vertexBuffer = new VertexBuffer3D(12 * 4, gl.STATIC_DRAW, false);
	        this._vertexBuffer.vertexDeclaration = ScreenTriangle._vertexDeclaration;
	        this._vertexBuffer.setData(ScreenTriangle._vertices.buffer);
	        this._bufferState.bind();
	        this._bufferState.applyVertexBuffer(this._vertexBuffer);
	        this._bufferState.unBind();
	        this._vertexBufferInvertUV = new VertexBuffer3D(12 * 4, gl.STATIC_DRAW, false);
	        this._vertexBufferInvertUV.vertexDeclaration = ScreenTriangle._vertexDeclaration;
	        this._vertexBufferInvertUV.setData(ScreenTriangle._verticesInvertUV.buffer);
	        this._bufferStateInvertUV.bind();
	        this._bufferStateInvertUV.applyVertexBuffer(this._vertexBufferInvertUV);
	        this._bufferStateInvertUV.unBind();
	        this._setGPUMemory(this._vertexBuffer._byteLength + this._vertexBufferInvertUV._byteLength);
	    }
	    static __init__() {
	        ScreenTriangle._vertexDeclaration = new VertexDeclaration(16, [new VertexElement(0, VertexElementFormat.Vector4, ScreenTriangle.SCREENTRIANGLE_POSITION_UV)]);
	        ScreenTriangle.instance = new ScreenTriangle();
	        ScreenTriangle.instance.lock = true;
	    }
	    render() {
	        var gl = Laya.LayaGL.instance;
	        this._bufferState.bind();
	        gl.drawArrays(gl.TRIANGLES, 0, 3);
	        Laya.Stat.renderBatches++;
	    }
	    renderInvertUV() {
	        var gl = Laya.LayaGL.instance;
	        this._bufferStateInvertUV.bind();
	        gl.drawArrays(gl.TRIANGLES, 0, 3);
	        Laya.Stat.renderBatches++;
	    }
	    destroy() {
	        super.destroy();
	        this._bufferState.destroy();
	        this._vertexBuffer.destroy();
	        this._bufferStateInvertUV.destroy();
	        this._vertexBufferInvertUV.destroy();
	        this._setGPUMemory(0);
	    }
	}
	ScreenTriangle.SCREENTRIANGLE_POSITION_UV = 0;
	ScreenTriangle._vertices = new Float32Array([-1, -1, 0, 1, -1, 3, 0, -1, 3, -1, 2, 1]);
	ScreenTriangle._verticesInvertUV = new Float32Array([-1, -1, 0, 0, -1, 3, 0, 2, 3, -1, 2, 0]);

	class Command {
	    constructor() {
	        this._commandBuffer = null;
	    }
	    static __init__() {
	        Command._screenShaderData = new ShaderData();
	        Command._screenShader = Shader3D.find("BlitScreen");
	    }
	    run() {
	    }
	    recover() {
	        this._commandBuffer = null;
	    }
	}
	Command.SCREENTEXTURE_NAME = "u_MainTex";
	Command.MAINTEXTURE_TEXELSIZE_NAME = "u_MainTex_TexelSize";
	Command.SCREENTEXTURE_ID = Shader3D.propertyNameToID(Command.SCREENTEXTURE_NAME);
	Command.MAINTEXTURE_TEXELSIZE_ID = Shader3D.propertyNameToID(Command.MAINTEXTURE_TEXELSIZE_NAME);

	class BlitScreenQuadCMD extends Command {
	    constructor() {
	        super(...arguments);
	        this._source = null;
	        this._dest = null;
	        this._shader = null;
	        this._shaderData = null;
	        this._subShader = 0;
	        this._sourceTexelSize = new Vector4();
	        this._screenType = 0;
	    }
	    static create(source, dest, shader = null, shaderData = null, subShader = 0, screenType = BlitScreenQuadCMD._SCREENTYPE_QUAD) {
	        var cmd;
	        cmd = BlitScreenQuadCMD._pool.length > 0 ? BlitScreenQuadCMD._pool.pop() : new BlitScreenQuadCMD();
	        cmd._source = source;
	        cmd._dest = dest;
	        cmd._shader = shader;
	        cmd._shaderData = shaderData;
	        cmd._subShader = subShader;
	        cmd._screenType = screenType;
	        return cmd;
	    }
	    run() {
	        var shader = this._shader || Command._screenShader;
	        var shaderData = this._shaderData || Command._screenShaderData;
	        var dest = this._dest;
	        Laya.LayaGL.instance.viewport(0, 0, dest ? dest.width : RenderContext3D.clientWidth, dest ? dest.height : RenderContext3D.clientHeight);
	        shaderData.setTexture(Command.SCREENTEXTURE_ID, this._source);
	        this._sourceTexelSize.setValue(1.0 / this._source.width, 1.0 / this._source.height, this._source.width, this._source.height);
	        shaderData.setVector(Command.MAINTEXTURE_TEXELSIZE_ID, this._sourceTexelSize);
	        (dest) && (dest._start());
	        var subShader = shader.getSubShaderAt(this._subShader);
	        var passes = subShader._passes;
	        for (var i = 0, n = passes.length; i < n; i++) {
	            var comDef = BlitScreenQuadCMD._compileDefine;
	            shaderData._defineDatas.cloneTo(comDef);
	            var shaderPass = passes[i].withCompile(comDef);
	            shaderPass.bind();
	            shaderPass.uploadUniforms(shaderPass._materialUniformParamsMap, shaderData, true);
	            shaderPass.uploadRenderStateBlendDepth(shaderData);
	            shaderPass.uploadRenderStateFrontFace(shaderData, false, null);
	            switch (this._screenType) {
	                case BlitScreenQuadCMD._SCREENTYPE_QUAD:
	                    dest ? ScreenQuad.instance.renderInvertUV() : ScreenQuad.instance.render();
	                    break;
	                case BlitScreenQuadCMD._SCREENTYPE_TRIANGLE:
	                    dest ? ScreenTriangle.instance.renderInvertUV() : ScreenTriangle.instance.render();
	                    break;
	                    throw "BlitScreenQuadCMD:unknown screen Type.";
	            }
	        }
	        (dest) && (dest._end());
	    }
	    recover() {
	        BlitScreenQuadCMD._pool.push(this);
	        this._dest = null;
	        this._shader = null;
	        this._shaderData = null;
	        super.recover();
	    }
	}
	BlitScreenQuadCMD._SCREENTYPE_QUAD = 0;
	BlitScreenQuadCMD._SCREENTYPE_TRIANGLE = 1;
	BlitScreenQuadCMD._compileDefine = new DefineDatas();
	BlitScreenQuadCMD._pool = [];

	class SetRenderTargetCMD extends Command {
	    constructor() {
	        super(...arguments);
	        this._renderTexture = null;
	    }
	    static create(renderTexture) {
	        var cmd;
	        cmd = SetRenderTargetCMD._pool.length > 0 ? SetRenderTargetCMD._pool.pop() : new SetRenderTargetCMD();
	        cmd._renderTexture = renderTexture;
	        return cmd;
	    }
	    run() {
	        this._renderTexture._start();
	    }
	    recover() {
	        SetRenderTargetCMD._pool.push(this);
	        this._renderTexture = null;
	    }
	}
	SetRenderTargetCMD._pool = [];

	class SetShaderDataTextureCMD extends Command {
	    constructor() {
	        super(...arguments);
	        this._shaderData = null;
	        this._nameID = 0;
	        this._texture = null;
	    }
	    static create(shaderData, nameID, texture) {
	        var cmd;
	        cmd = SetShaderDataTextureCMD._pool.length > 0 ? SetShaderDataTextureCMD._pool.pop() : new SetShaderDataTextureCMD();
	        cmd._shaderData = shaderData;
	        cmd._nameID = nameID;
	        cmd._texture = texture;
	        return cmd;
	    }
	    run() {
	        this._shaderData.setTexture(this._nameID, this._texture);
	    }
	    recover() {
	        SetShaderDataTextureCMD._pool.push(this);
	        this._shaderData = null;
	        this._nameID = 0;
	        this._texture = null;
	    }
	}
	SetShaderDataTextureCMD._pool = [];

	class CommandBuffer {
	    constructor() {
	        this._camera = null;
	        this._commands = [];
	    }
	    _apply() {
	        for (var i = 0, n = this._commands.length; i < n; i++)
	            this._commands[i].run();
	    }
	    setShaderDataTexture(shaderData, nameID, source) {
	        this._commands.push(SetShaderDataTextureCMD.create(shaderData, nameID, source));
	    }
	    blitScreenQuad(source, dest, shader = null, shaderData = null, subShader = 0) {
	        this._commands.push(BlitScreenQuadCMD.create(source, dest, shader, shaderData, subShader, BlitScreenQuadCMD._SCREENTYPE_QUAD));
	    }
	    blitScreenTriangle(source, dest, shader = null, shaderData = null, subShader = 0) {
	        this._commands.push(BlitScreenQuadCMD.create(source, dest, shader, shaderData, subShader, BlitScreenQuadCMD._SCREENTYPE_TRIANGLE));
	    }
	    setRenderTarget(renderTexture) {
	        this._commands.push(SetRenderTargetCMD.create(renderTexture));
	    }
	    clear() {
	        for (var i = 0, n = this._commands.length; i < n; i++)
	            this._commands[i].recover();
	        this._commands.length = 0;
	    }
	}

	class Camera extends BaseCamera {
	    constructor(aspectRatio = 0, nearPlane = 0.3, farPlane = 1000) {
	        super(nearPlane, farPlane);
	        this._updateViewMatrix = true;
	        this._postProcess = null;
	        this._enableHDR = false;
	        this._viewportParams = new Vector4();
	        this._projectionParams = new Vector4();
	        this._offScreenRenderTexture = null;
	        this._renderTexture = null;
	        this._postProcessCommandBuffers = [];
	        this._clusterPlaneCacheFlag = new Vector2(-1, -1);
	        this.enableRender = true;
	        this._viewMatrix = new Matrix4x4();
	        this._projectionMatrix = new Matrix4x4();
	        this._projectionViewMatrix = new Matrix4x4();
	        this._viewport = new Viewport(0, 0, 0, 0);
	        this._normalizedViewport = new Viewport(0, 0, 1, 1);
	        this._aspectRatio = aspectRatio;
	        this._boundFrustum = new BoundFrustum(Matrix4x4.DEFAULT);
	        if (Laya.Render.supportWebGLPlusCulling)
	            this._boundFrustumBuffer = new Float32Array(24);
	        this._calculateProjectionMatrix();
	        Laya.Laya.stage.on(Laya.Event.RESIZE, this, this._onScreenSizeChanged);
	        this.transform.on(Laya.Event.TRANSFORM_CHANGED, this, this._onTransformChanged);
	    }
	    get aspectRatio() {
	        if (this._aspectRatio === 0) {
	            var vp = this.viewport;
	            return vp.width / vp.height;
	        }
	        return this._aspectRatio;
	    }
	    set aspectRatio(value) {
	        if (value < 0)
	            throw new Error("Camera: the aspect ratio has to be a positive real number.");
	        this._aspectRatio = value;
	        this._calculateProjectionMatrix();
	    }
	    get viewport() {
	        if (this._offScreenRenderTexture)
	            this._calculationViewport(this._normalizedViewport, this._offScreenRenderTexture.width, this._offScreenRenderTexture.height);
	        else
	            this._calculationViewport(this._normalizedViewport, RenderContext3D.clientWidth, RenderContext3D.clientHeight);
	        return this._viewport;
	    }
	    set viewport(value) {
	        var width;
	        var height;
	        if (this._offScreenRenderTexture) {
	            width = this._offScreenRenderTexture.width;
	            height = this._offScreenRenderTexture.height;
	        }
	        else {
	            width = RenderContext3D.clientWidth;
	            height = RenderContext3D.clientHeight;
	        }
	        this._normalizedViewport.x = value.x / width;
	        this._normalizedViewport.y = value.y / height;
	        this._normalizedViewport.width = value.width / width;
	        this._normalizedViewport.height = value.height / height;
	        this._calculationViewport(this._normalizedViewport, width, height);
	        this._calculateProjectionMatrix();
	    }
	    get normalizedViewport() {
	        return this._normalizedViewport;
	    }
	    set normalizedViewport(value) {
	        var width;
	        var height;
	        if (this._offScreenRenderTexture) {
	            width = this._offScreenRenderTexture.width;
	            height = this._offScreenRenderTexture.height;
	        }
	        else {
	            width = RenderContext3D.clientWidth;
	            height = RenderContext3D.clientHeight;
	        }
	        if (this._normalizedViewport !== value)
	            value.cloneTo(this._normalizedViewport);
	        this._calculationViewport(value, width, height);
	        this._calculateProjectionMatrix();
	    }
	    get viewMatrix() {
	        if (this._updateViewMatrix) {
	            var scale = this.transform.getWorldLossyScale();
	            var scaleX = scale.x;
	            var scaleY = scale.y;
	            var scaleZ = scale.z;
	            var viewMatE = this._viewMatrix.elements;
	            this.transform.worldMatrix.cloneTo(this._viewMatrix);
	            viewMatE[0] /= scaleX;
	            viewMatE[1] /= scaleX;
	            viewMatE[2] /= scaleX;
	            viewMatE[4] /= scaleY;
	            viewMatE[5] /= scaleY;
	            viewMatE[6] /= scaleY;
	            viewMatE[8] /= scaleZ;
	            viewMatE[9] /= scaleZ;
	            viewMatE[10] /= scaleZ;
	            this._viewMatrix.invert(this._viewMatrix);
	            this._updateViewMatrix = false;
	        }
	        return this._viewMatrix;
	    }
	    get projectionMatrix() {
	        return this._projectionMatrix;
	    }
	    set projectionMatrix(value) {
	        this._projectionMatrix = value;
	        this._useUserProjectionMatrix = true;
	    }
	    get projectionViewMatrix() {
	        Matrix4x4.multiply(this.projectionMatrix, this.viewMatrix, this._projectionViewMatrix);
	        return this._projectionViewMatrix;
	    }
	    get boundFrustum() {
	        this._boundFrustum.matrix = this.projectionViewMatrix;
	        if (Laya.Render.supportWebGLPlusCulling) {
	            var near = this._boundFrustum.near;
	            var far = this._boundFrustum.far;
	            var left = this._boundFrustum.left;
	            var right = this._boundFrustum.right;
	            var top = this._boundFrustum.top;
	            var bottom = this._boundFrustum.bottom;
	            var nearNE = near.normal;
	            var farNE = far.normal;
	            var leftNE = left.normal;
	            var rightNE = right.normal;
	            var topNE = top.normal;
	            var bottomNE = bottom.normal;
	            var buffer = this._boundFrustumBuffer;
	            buffer[0] = nearNE.x, buffer[1] = nearNE.y, buffer[2] = nearNE.z, buffer[3] = near.distance;
	            buffer[4] = farNE.x, buffer[5] = farNE.y, buffer[6] = farNE.z, buffer[7] = far.distance;
	            buffer[8] = leftNE.x, buffer[9] = leftNE.y, buffer[10] = leftNE.z, buffer[11] = left.distance;
	            buffer[12] = rightNE.x, buffer[13] = rightNE.y, buffer[14] = rightNE.z, buffer[15] = right.distance;
	            buffer[16] = topNE.x, buffer[17] = topNE.y, buffer[18] = topNE.z, buffer[19] = top.distance;
	            buffer[20] = bottomNE.x, buffer[21] = bottomNE.y, buffer[22] = bottomNE.z, buffer[23] = bottom.distance;
	        }
	        return this._boundFrustum;
	    }
	    get renderTarget() {
	        return this._offScreenRenderTexture;
	    }
	    set renderTarget(value) {
	        if (this._offScreenRenderTexture !== value) {
	            this._offScreenRenderTexture = value;
	            this._calculateProjectionMatrix();
	        }
	    }
	    get postProcess() {
	        return this._postProcess;
	    }
	    set postProcess(value) {
	        this._postProcess = value;
	        var postProcessCommandBuffer = new CommandBuffer();
	        this.addCommandBuffer(Camera.CAMERAEVENT_POSTPROCESS, postProcessCommandBuffer);
	        value._init(this, postProcessCommandBuffer);
	    }
	    get enableHDR() {
	        return this._enableHDR;
	    }
	    set enableHDR(value) {
	        if (value) {
	            if (SystemUtils.supportRenderTextureFormat(Laya.RenderTextureFormat.R16G16B16A16))
	                this._enableHDR = true;
	            else
	                console.warn("Camera:can't enable HDR in this device.");
	        }
	        else {
	            this._enableHDR = false;
	        }
	    }
	    _calculationViewport(normalizedViewport, width, height) {
	        var lx = normalizedViewport.x * width;
	        var ly = normalizedViewport.y * height;
	        var rx = lx + Math.max(normalizedViewport.width * width, 0);
	        var ry = ly + Math.max(normalizedViewport.height * height, 0);
	        var ceilLeftX = Math.ceil(lx);
	        var ceilLeftY = Math.ceil(ly);
	        var floorRightX = Math.floor(rx);
	        var floorRightY = Math.floor(ry);
	        var pixelLeftX = ceilLeftX - lx >= 0.5 ? Math.floor(lx) : ceilLeftX;
	        var pixelLeftY = ceilLeftY - ly >= 0.5 ? Math.floor(ly) : ceilLeftY;
	        var pixelRightX = rx - floorRightX >= 0.5 ? Math.ceil(rx) : floorRightX;
	        var pixelRightY = ry - floorRightY >= 0.5 ? Math.ceil(ry) : floorRightY;
	        this._viewport.x = pixelLeftX;
	        this._viewport.y = pixelLeftY;
	        this._viewport.width = pixelRightX - pixelLeftX;
	        this._viewport.height = pixelRightY - pixelLeftY;
	    }
	    _calculateProjectionMatrix() {
	        if (!this._useUserProjectionMatrix) {
	            if (this._orthographic) {
	                var halfHeight = this.orthographicVerticalSize * 0.5;
	                var halfWidth = halfHeight * this.aspectRatio;
	                Matrix4x4.createOrthoOffCenter(-halfWidth, halfWidth, -halfHeight, halfHeight, this.nearPlane, this.farPlane, this._projectionMatrix);
	            }
	            else {
	                Matrix4x4.createPerspective(3.1416 * this.fieldOfView / 180.0, this.aspectRatio, this.nearPlane, this.farPlane, this._projectionMatrix);
	            }
	        }
	    }
	    _isLayerVisible(layer) {
	        return (Math.pow(2, layer) & this.cullingMask) != 0;
	    }
	    _onTransformChanged(flag) {
	        flag &= Transform3D.TRANSFORM_WORLDMATRIX;
	        (flag) && (this._updateViewMatrix = true);
	    }
	    _parse(data, spriteMap) {
	        super._parse(data, spriteMap);
	        var viewport = data.viewport;
	        this.normalizedViewport = new Viewport(viewport[0], viewport[1], viewport[2], viewport[3]);
	        var enableHDR = data.enableHDR;
	        (enableHDR !== undefined) && (this.enableHDR = enableHDR);
	    }
	    _getCanvasHeight() {
	        if (this._offScreenRenderTexture)
	            return this._offScreenRenderTexture.height;
	        else
	            return RenderContext3D.clientHeight;
	    }
	    _getInternalRenderTexture() {
	        return this._renderTexture || this._offScreenRenderTexture;
	    }
	    _applyPostProcessCommandBuffers() {
	        for (var i = 0, n = this._postProcessCommandBuffers.length; i < n; i++)
	            this._postProcessCommandBuffers[i]._apply();
	    }
	    _getRenderTextureFormat() {
	        if (this._enableHDR)
	            return Laya.RenderTextureFormat.R16G16B16A16;
	        else
	            return Laya.RenderTextureFormat.R8G8B8;
	    }
	    _prepareCameraToRender() {
	        super._prepareCameraToRender();
	        var vp = this.viewport;
	        this._viewportParams.setValue(vp.x, vp.y, vp.width, vp.height);
	        this._projectionParams.setValue(this._nearPlane, this._farPlane, this._getInternalRenderTexture() ? -1 : 1, 0);
	        this._shaderValues.setVector(BaseCamera.VIEWPORT, this._viewportParams);
	        this._shaderValues.setVector(BaseCamera.PROJECTION_PARAMS, this._projectionParams);
	    }
	    _applyViewProject(context, viewMat, proMat, inverseY) {
	        var projectView;
	        var shaderData = this._shaderValues;
	        if (inverseY) {
	            Matrix4x4.multiply(BaseCamera._invertYScaleMatrix, proMat, BaseCamera._invertYProjectionMatrix);
	            Matrix4x4.multiply(BaseCamera._invertYProjectionMatrix, viewMat, BaseCamera._invertYProjectionViewMatrix);
	            proMat = BaseCamera._invertYProjectionMatrix;
	            projectView = BaseCamera._invertYProjectionViewMatrix;
	        }
	        else {
	            Matrix4x4.multiply(proMat, viewMat, this._projectionViewMatrix);
	            projectView = this._projectionViewMatrix;
	        }
	        context.viewMatrix = viewMat;
	        context.projectionMatrix = proMat;
	        context.projectionViewMatrix = projectView;
	        shaderData.setMatrix4x4(BaseCamera.VIEWMATRIX, viewMat);
	        shaderData.setMatrix4x4(BaseCamera.PROJECTMATRIX, proMat);
	        shaderData.setMatrix4x4(BaseCamera.VIEWPROJECTMATRIX, projectView);
	    }
	    _updateClusterPlaneXY() {
	        var fieldOfView = this.fieldOfView;
	        var aspectRatio = this.aspectRatio;
	        if (this._clusterPlaneCacheFlag.x !== fieldOfView || this._clusterPlaneCacheFlag.y !== aspectRatio) {
	            var clusterCount = Config3D._config.lightClusterCount;
	            var xSlixe = clusterCount.x, ySlice = clusterCount.y;
	            var xCount = xSlixe + 1, yCount = ySlice + 1;
	            var xPlanes = this._clusterXPlanes, yPlanes = this._clusterYPlanes;
	            if (!xPlanes) {
	                xPlanes = this._clusterXPlanes = new Array(xCount);
	                yPlanes = this._clusterYPlanes = new Array(yCount);
	                for (var i = 0; i < xCount; i++)
	                    xPlanes[i] = new Vector3();
	                for (var i = 0; i < yCount; i++)
	                    yPlanes[i] = new Vector3();
	            }
	            var halfY = Math.tan((this.fieldOfView / 2) * Math.PI / 180);
	            var halfX = this.aspectRatio * halfY;
	            var yLengthPerCluster = 2 * halfY / xSlixe;
	            var xLengthPerCluster = 2 * halfX / ySlice;
	            for (var i = 0; i < xCount; i++) {
	                var angle = -halfX + xLengthPerCluster * i;
	                var bigHypot = Math.sqrt(1 + angle * angle);
	                var normX = 1 / bigHypot;
	                var xPlane = xPlanes[i];
	                xPlane.setValue(normX, 0, -angle * normX);
	            }
	            for (var i = 0; i < yCount; i++) {
	                var angle = halfY - yLengthPerCluster * i;
	                var bigHypot = Math.sqrt(1 + angle * angle);
	                var normY = -1 / bigHypot;
	                var yPlane = yPlanes[i];
	                yPlane.setValue(0, normY, -angle * normY);
	            }
	            this._clusterPlaneCacheFlag.x = fieldOfView;
	            this._clusterPlaneCacheFlag.y = aspectRatio;
	        }
	    }
	    render(shader = null, replacementTag = null) {
	        if (!this._scene)
	            return;
	        var createRenderTexture = this._postProcess || this._enableHDR ? true : false;
	        if (createRenderTexture)
	            this._renderTexture = RenderTexture.createFromPool(RenderContext3D.clientWidth, RenderContext3D.clientHeight, this._getRenderTextureFormat(), Laya.RenderTextureDepthFormat.DEPTH_16, Laya.BaseTexture.FILTERMODE_BILINEAR);
	        var gl = Laya.LayaGL.instance;
	        var context = RenderContext3D._instance;
	        var scene = context.scene = this._scene;
	        if (scene.parallelSplitShadowMaps[0]) {
	            ShaderData.setRuntimeValueMode(false);
	            var parallelSplitShadowMap = scene.parallelSplitShadowMaps[0];
	            parallelSplitShadowMap._calcAllLightCameraInfo(this);
	            scene._shaderValues.addDefine(Scene3DShaderDeclaration.SHADERDEFINE_CAST_SHADOW);
	            for (var i = 0, n = parallelSplitShadowMap.shadowMapCount; i < n; i++) {
	                var smCamera = parallelSplitShadowMap.cameras[i];
	                context.camera = smCamera;
	                FrustumCulling.renderObjectCulling(smCamera, scene, context, scene._castShadowRenders, shader, replacementTag);
	                var shadowMap = parallelSplitShadowMap.cameras[i + 1].renderTarget;
	                shadowMap._start();
	                context.camera = smCamera;
	                Camera._updateMark++;
	                context.viewport = smCamera.viewport;
	                smCamera._prepareCameraToRender();
	                smCamera._applyViewProject(context, smCamera.viewMatrix, smCamera.projectionMatrix, false);
	                scene._clear(gl, context);
	                var queue = scene._opaqueQueue;
	                queue._render(context, false);
	                shadowMap._end();
	            }
	            scene._shaderValues.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_CAST_SHADOW);
	            ShaderData.setRuntimeValueMode(true);
	        }
	        context.camera = this;
	        Camera._updateMark++;
	        scene._preRenderScript();
	        var renderTar = this._getInternalRenderTexture();
	        (renderTar) && (renderTar._start());
	        context.viewport = this.viewport;
	        this._prepareCameraToRender();
	        var multiLighting = Config3D._config._multiLighting;
	        (multiLighting) && (Cluster.instance.update(this, (this._scene)));
	        this._applyViewProject(context, this.viewMatrix, this._projectionMatrix, renderTar ? true : false);
	        scene._preCulling(context, this, shader, replacementTag);
	        scene._clear(gl, context);
	        scene._renderScene(context);
	        scene._postRenderScript();
	        (renderTar) && (renderTar._end());
	        if (createRenderTexture) {
	            if (this._postProcess) {
	                this._postProcess._render();
	                this._applyPostProcessCommandBuffers();
	            }
	            else if (this._enableHDR) {
	                var blit = BlitScreenQuadCMD.create(this._renderTexture, this._offScreenRenderTexture ? this._offScreenRenderTexture : null);
	                blit.run();
	                blit.recover();
	            }
	            RenderTexture.recoverToPool(this._renderTexture);
	        }
	    }
	    viewportPointToRay(point, out) {
	        Picker.calculateCursorRay(point, this.viewport, this._projectionMatrix, this.viewMatrix, null, out);
	    }
	    normalizedViewportPointToRay(point, out) {
	        var finalPoint = Camera._tempVector20;
	        var vp = this.viewport;
	        finalPoint.x = point.x * vp.width;
	        finalPoint.y = point.y * vp.height;
	        Picker.calculateCursorRay(finalPoint, this.viewport, this._projectionMatrix, this.viewMatrix, null, out);
	    }
	    worldToViewportPoint(position, out) {
	        Matrix4x4.multiply(this._projectionMatrix, this._viewMatrix, this._projectionViewMatrix);
	        this.viewport.project(position, this._projectionViewMatrix, out);
	        out.x = out.x / Laya.Laya.stage.clientScaleX;
	        out.y = out.y / Laya.Laya.stage.clientScaleY;
	    }
	    worldToNormalizedViewportPoint(position, out) {
	        Matrix4x4.multiply(this._projectionMatrix, this._viewMatrix, this._projectionViewMatrix);
	        this.normalizedViewport.project(position, this._projectionViewMatrix, out);
	        out.x = out.x / Laya.Laya.stage.clientScaleX;
	        out.y = out.y / Laya.Laya.stage.clientScaleY;
	    }
	    convertScreenCoordToOrthographicCoord(source, out) {
	        if (this._orthographic) {
	            var clientWidth = RenderContext3D.clientWidth;
	            var clientHeight = RenderContext3D.clientHeight;
	            var ratioX = this.orthographicVerticalSize * this.aspectRatio / clientWidth;
	            var ratioY = this.orthographicVerticalSize / clientHeight;
	            out.x = (-clientWidth / 2 + source.x * Laya.Laya.stage.clientScaleX) * ratioX;
	            out.y = (clientHeight / 2 - source.y * Laya.Laya.stage.clientScaleY) * ratioY;
	            out.z = (this.nearPlane - this.farPlane) * (source.z + 1) / 2 - this.nearPlane;
	            Vector3.transformCoordinate(out, this.transform.worldMatrix, out);
	            return true;
	        }
	        else {
	            return false;
	        }
	    }
	    destroy(destroyChild = true) {
	        this._offScreenRenderTexture = null;
	        this.transform.off(Laya.Event.TRANSFORM_CHANGED, this, this._onTransformChanged);
	        super.destroy(destroyChild);
	    }
	    addCommandBuffer(event, commandBuffer) {
	        switch (event) {
	            case Camera.CAMERAEVENT_POSTPROCESS:
	                this._postProcessCommandBuffers.push(commandBuffer);
	                commandBuffer._camera = this;
	                break;
	            default:
	                throw "Camera:unknown event.";
	        }
	    }
	    removeCommandBuffer(event, commandBuffer) {
	        switch (event) {
	            case Camera.CAMERAEVENT_POSTPROCESS:
	                var index = this._postProcessCommandBuffers.indexOf(commandBuffer);
	                if (index !== -1)
	                    this._postProcessCommandBuffers.splice(index, 1);
	                break;
	            default:
	                throw "Camera:unknown event.";
	        }
	    }
	    removeCommandBuffers(event) {
	        switch (event) {
	            case Camera.CAMERAEVENT_POSTPROCESS:
	                this._postProcessCommandBuffers.length = 0;
	                break;
	            default:
	                throw "Camera:unknown event.";
	        }
	    }
	    _create() {
	        return new Camera();
	    }
	}
	Camera.CAMERAEVENT_POSTPROCESS = 0;
	Camera._tempVector20 = new Vector2();
	Camera._updateMark = 0;

	class RenderElement {
	    constructor() {
	        this.renderSubShader = null;
	        this.renderType = RenderElement.RENDERTYPE_NORMAL;
	    }
	    getInvertFront() {
	        return this._transform._isFrontFaceInvert;
	    }
	    setTransform(transform) {
	        this._transform = transform;
	    }
	    setGeometry(geometry) {
	        this._geometry = geometry;
	    }
	    addToOpaqueRenderQueue(context, queue) {
	        queue.elements.add(this);
	    }
	    addToTransparentRenderQueue(context, queue) {
	        queue.elements.add(this);
	        queue.lastTransparentBatched = false;
	        queue.lastTransparentRenderElement = this;
	    }
	    _update(scene, context, customShader, replacementTag) {
	        if (this.material) {
	            var subShader = this.material._shader.getSubShaderAt(0);
	            this.renderSubShader = null;
	            if (customShader) {
	                if (replacementTag) {
	                    var oriTag = subShader.getFlag(replacementTag);
	                    if (oriTag) {
	                        var customSubShaders = customShader._subShaders;
	                        for (var k = 0, p = customSubShaders.length; k < p; k++) {
	                            var customSubShader = customSubShaders[k];
	                            if (oriTag === customSubShader.getFlag(replacementTag)) {
	                                this.renderSubShader = customSubShader;
	                                break;
	                            }
	                        }
	                        if (!this.renderSubShader)
	                            return;
	                    }
	                    else {
	                        return;
	                    }
	                }
	                else {
	                    this.renderSubShader = customShader.getSubShaderAt(0);
	                }
	            }
	            else {
	                this.renderSubShader = subShader;
	            }
	            var renderQueue = scene._getRenderQueue(this.material.renderQueue);
	            if (renderQueue.isTransparent)
	                this.addToTransparentRenderQueue(context, renderQueue);
	            else
	                this.addToOpaqueRenderQueue(context, renderQueue);
	        }
	    }
	    _render(context, isTarget) {
	        var lastStateMaterial, lastStateShaderInstance, lastStateRender;
	        var updateMark = Camera._updateMark;
	        var scene = context.scene;
	        var camera = context.camera;
	        var transform = this._transform;
	        var geometry = this._geometry;
	        context.renderElement = this;
	        var updateRender = updateMark !== this.render._updateMark || this.renderType !== this.render._updateRenderType;
	        if (updateRender) {
	            this.render._renderUpdate(context, transform);
	            this.render._renderUpdateWithCamera(context, transform);
	            this.render._updateMark = updateMark;
	            this.render._updateRenderType = this.renderType;
	        }
	        else {
	            if (this.renderType == RenderElement.RENDERTYPE_INSTANCEBATCH) {
	                this.render._renderUpdate(context, transform);
	                this.render._renderUpdateWithCamera(context, transform);
	            }
	        }
	        if (geometry._prepareRender(context)) {
	            var passes = this.renderSubShader._passes;
	            for (var j = 0, m = passes.length; j < m; j++) {
	                var comDef = RenderElement._compileDefine;
	                scene._shaderValues._defineDatas.cloneTo(comDef);
	                comDef.removeDefineDatas(this.material._disablePublicDefineDatas);
	                comDef.addDefineDatas(this.render._shaderValues._defineDatas);
	                comDef.addDefineDatas(this.material._shaderValues._defineDatas);
	                var shaderIns = context.shader = passes[j].withCompile(comDef);
	                var switchShader = shaderIns.bind();
	                var switchUpdateMark = (updateMark !== shaderIns._uploadMark);
	                var uploadScene = (shaderIns._uploadScene !== scene) || switchUpdateMark;
	                if (uploadScene || switchShader) {
	                    shaderIns.uploadUniforms(shaderIns._sceneUniformParamsMap, scene._shaderValues, uploadScene);
	                    shaderIns._uploadScene = scene;
	                }
	                var uploadSprite3D = (shaderIns._uploadRender !== this.render || shaderIns._uploadRenderType !== this.renderType) || switchUpdateMark;
	                if (uploadSprite3D || switchShader) {
	                    shaderIns.uploadUniforms(shaderIns._spriteUniformParamsMap, this.render._shaderValues, uploadSprite3D);
	                    shaderIns._uploadRender = this.render;
	                    shaderIns._uploadRenderType = this.renderType;
	                }
	                var uploadCamera = shaderIns._uploadCamera !== camera || switchUpdateMark;
	                if (uploadCamera || switchShader) {
	                    shaderIns.uploadUniforms(shaderIns._cameraUniformParamsMap, camera._shaderValues, uploadCamera);
	                    shaderIns._uploadCamera = camera;
	                }
	                var uploadMaterial = (shaderIns._uploadMaterial !== this.material) || switchUpdateMark;
	                if (uploadMaterial || switchShader) {
	                    shaderIns.uploadUniforms(shaderIns._materialUniformParamsMap, this.material._shaderValues, uploadMaterial);
	                    shaderIns._uploadMaterial = this.material;
	                }
	                var matValues = this.material._shaderValues;
	                if (lastStateMaterial !== this.material || lastStateShaderInstance !== shaderIns) {
	                    shaderIns.uploadRenderStateBlendDepth(matValues);
	                    shaderIns.uploadRenderStateFrontFace(matValues, isTarget, this.getInvertFront());
	                    lastStateMaterial = this.material;
	                    lastStateShaderInstance = shaderIns;
	                    lastStateRender = this.render;
	                }
	                else {
	                    if (lastStateRender !== this.render) {
	                        shaderIns.uploadRenderStateFrontFace(matValues, isTarget, this.getInvertFront());
	                        lastStateRender = this.render;
	                    }
	                }
	                geometry._render(context);
	                shaderIns._uploadMark = updateMark;
	            }
	        }
	        if (updateRender && this.renderType !== RenderElement.RENDERTYPE_NORMAL)
	            this.render._revertBatchRenderUpdate(context);
	    }
	    destroy() {
	        this._transform = null;
	        this._geometry = null;
	        this.material = null;
	        this.render = null;
	    }
	}
	RenderElement.RENDERTYPE_NORMAL = 0;
	RenderElement.RENDERTYPE_STATICBATCH = 1;
	RenderElement.RENDERTYPE_INSTANCEBATCH = 2;
	RenderElement.RENDERTYPE_VERTEXBATCH = 3;
	RenderElement._compileDefine = new DefineDatas();

	class SubMeshRenderElement extends RenderElement {
	    constructor() {
	        super();
	        this._dynamicWorldPositionNormalNeedUpdate = true;
	    }
	    _onWorldMatrixChanged() {
	        this._dynamicWorldPositionNormalNeedUpdate = true;
	    }
	    _computeWorldPositionsAndNormals(positionOffset, normalOffset, multiSubMesh, vertexCount) {
	        if (this._dynamicWorldPositionNormalNeedUpdate) {
	            var subMesh = this._geometry;
	            var vertexBuffer = subMesh._vertexBuffer;
	            var vertexFloatCount = vertexBuffer.vertexDeclaration.vertexStride / 4;
	            var oriVertexes = vertexBuffer.getFloat32Data();
	            var worldMat = this._transform.worldMatrix;
	            var rotation = this._transform.rotation;
	            var indices = subMesh._indices;
	            for (var i = 0; i < vertexCount; i++) {
	                var index = multiSubMesh ? indices[i] : i;
	                var oriOffset = index * vertexFloatCount;
	                var bakeOffset = i * 3;
	                Utils3D.transformVector3ArrayToVector3ArrayCoordinate(oriVertexes, oriOffset + positionOffset, worldMat, this._dynamicWorldPositions, bakeOffset);
	                (normalOffset !== -1) && (Utils3D.transformVector3ArrayByQuat(oriVertexes, oriOffset + normalOffset, rotation, this._dynamicWorldNormals, bakeOffset));
	            }
	            this._dynamicWorldPositionNormalNeedUpdate = false;
	        }
	    }
	    setTransform(transform) {
	        if (this._transform !== transform) {
	            (this._transform) && (this._transform.off(Laya.Event.TRANSFORM_CHANGED, this, this._onWorldMatrixChanged));
	            (transform) && (transform.on(Laya.Event.TRANSFORM_CHANGED, this, this._onWorldMatrixChanged));
	            this._dynamicWorldPositionNormalNeedUpdate = true;
	            this._transform = transform;
	        }
	    }
	    setGeometry(geometry) {
	        if (this._geometry !== geometry) {
	            var subMesh = geometry;
	            var mesh = subMesh._mesh;
	            if (mesh) {
	                var multiSubMesh = mesh._subMeshes.length > 1;
	                var dynBatVerCount = multiSubMesh ? subMesh._indexCount : mesh._vertexCount;
	                if (dynBatVerCount <= ILaya3D.SubMeshDynamicBatch.maxAllowVertexCount) {
	                    var length = dynBatVerCount * 3;
	                    this._dynamicVertexBatch = true;
	                    this._dynamicWorldPositions = new Float32Array(length);
	                    this._dynamicWorldNormals = new Float32Array(length);
	                    this._dynamicVertexCount = dynBatVerCount;
	                    this._dynamicMultiSubMesh = multiSubMesh;
	                }
	                else {
	                    this._dynamicVertexBatch = false;
	                }
	            }
	            this._geometry = geometry;
	        }
	    }
	    addToOpaqueRenderQueue(context, queue) {
	        var subMeshStaticBatch = this.staticBatch;
	        var queueElements = queue.elements;
	        var elements = queueElements.elements;
	        if (subMeshStaticBatch) {
	            var staManager = ILaya3D.MeshRenderStaticBatchManager.instance;
	            var staBatchMarks = staManager.getBatchOpaquaMark(this.render.lightmapIndex + 1, this.render.receiveShadow, this.material.id, subMeshStaticBatch._batchID);
	            if (staManager._updateCountMark === staBatchMarks.updateMark) {
	                var staBatchIndex = staBatchMarks.indexInList;
	                if (staBatchMarks.batched) {
	                    elements[staBatchIndex].staticBatchElementList.add(this);
	                }
	                else {
	                    var staOriElement = elements[staBatchIndex];
	                    var staOriRender = staOriElement.render;
	                    var staBatchElement = staManager._getBatchRenderElementFromPool();
	                    staBatchElement.renderType = RenderElement.RENDERTYPE_STATICBATCH;
	                    staBatchElement.setGeometry(subMeshStaticBatch);
	                    staBatchElement.material = staOriElement.material;
	                    var staRootOwner = subMeshStaticBatch.batchOwner;
	                    var staBatchTransform = staRootOwner ? staRootOwner._transform : null;
	                    staBatchElement.setTransform(staBatchTransform);
	                    staBatchElement.render = staOriRender;
	                    staBatchElement.renderSubShader = staOriElement.renderSubShader;
	                    var staBatchList = staBatchElement.staticBatchElementList;
	                    staBatchList.length = 0;
	                    staBatchList.add(staOriElement);
	                    staBatchList.add(this);
	                    elements[staBatchIndex] = staBatchElement;
	                    staBatchMarks.batched = true;
	                }
	            }
	            else {
	                staBatchMarks.updateMark = staManager._updateCountMark;
	                staBatchMarks.indexInList = queueElements.length;
	                staBatchMarks.batched = false;
	                queueElements.add(this);
	            }
	        }
	        else if (this.renderSubShader._owner._enableInstancing && Laya.LayaGL.layaGPUInstance.supportInstance() && this.render.lightmapIndex < 0) {
	            var subMesh = this._geometry;
	            var insManager = ILaya3D.MeshRenderDynamicBatchManager.instance;
	            var insBatchMarks = insManager.getInstanceBatchOpaquaMark(this.render.receiveShadow, this.material.id, subMesh._id, this._transform._isFrontFaceInvert);
	            if (insManager._updateCountMark === insBatchMarks.updateMark) {
	                var insBatchIndex = insBatchMarks.indexInList;
	                if (insBatchMarks.batched) {
	                    var instanceBatchElementList = elements[insBatchIndex].instanceBatchElementList;
	                    if (instanceBatchElementList.length === SubMeshInstanceBatch.instance.maxInstanceCount) {
	                        insBatchMarks.updateMark = insManager._updateCountMark;
	                        insBatchMarks.indexInList = queueElements.length;
	                        insBatchMarks.batched = false;
	                        queueElements.add(this);
	                    }
	                    else {
	                        instanceBatchElementList.add(this);
	                    }
	                }
	                else {
	                    var insOriElement = elements[insBatchIndex];
	                    var insOriRender = insOriElement.render;
	                    var insBatchElement = insManager._getBatchRenderElementFromPool();
	                    insBatchElement.renderType = RenderElement.RENDERTYPE_INSTANCEBATCH;
	                    insBatchElement.setGeometry(SubMeshInstanceBatch.instance);
	                    insBatchElement.material = insOriElement.material;
	                    insBatchElement.setTransform(null);
	                    insBatchElement.render = insOriRender;
	                    insBatchElement.instanceSubMesh = subMesh;
	                    insBatchElement.renderSubShader = insOriElement.renderSubShader;
	                    var insBatchList = insBatchElement.instanceBatchElementList;
	                    insBatchList.length = 0;
	                    insBatchList.add(insOriElement);
	                    insBatchList.add(this);
	                    elements[insBatchIndex] = insBatchElement;
	                    insBatchMarks.batched = true;
	                }
	            }
	            else {
	                insBatchMarks.updateMark = insManager._updateCountMark;
	                insBatchMarks.indexInList = queueElements.length;
	                insBatchMarks.batched = false;
	                queueElements.add(this);
	            }
	        }
	        else if (this._dynamicVertexBatch) {
	            var verDec = this._geometry._vertexBuffer.vertexDeclaration;
	            var dynManager = ILaya3D.MeshRenderDynamicBatchManager.instance;
	            var dynBatchMarks = dynManager.getVertexBatchOpaquaMark(this.render.lightmapIndex + 1, this.render.receiveShadow, this.material.id, verDec.id);
	            if (dynManager._updateCountMark === dynBatchMarks.updateMark) {
	                var dynBatchIndex = dynBatchMarks.indexInList;
	                if (dynBatchMarks.batched) {
	                    elements[dynBatchIndex].vertexBatchElementList.add(this);
	                }
	                else {
	                    var dynOriElement = elements[dynBatchIndex];
	                    var dynOriRender = dynOriElement.render;
	                    var dynBatchElement = dynManager._getBatchRenderElementFromPool();
	                    dynBatchElement.renderType = RenderElement.RENDERTYPE_VERTEXBATCH;
	                    dynBatchElement.setGeometry(ILaya3D.SubMeshDynamicBatch.instance);
	                    dynBatchElement.material = dynOriElement.material;
	                    dynBatchElement.setTransform(null);
	                    dynBatchElement.render = dynOriRender;
	                    dynBatchElement.vertexBatchVertexDeclaration = verDec;
	                    dynBatchElement.renderSubShader = dynOriElement.renderSubShader;
	                    var dynBatchList = dynBatchElement.vertexBatchElementList;
	                    dynBatchList.length = 0;
	                    dynBatchList.add(dynOriElement);
	                    dynBatchList.add(this);
	                    elements[dynBatchIndex] = dynBatchElement;
	                    dynBatchMarks.batched = true;
	                }
	            }
	            else {
	                dynBatchMarks.updateMark = dynManager._updateCountMark;
	                dynBatchMarks.indexInList = queueElements.length;
	                dynBatchMarks.batched = false;
	                queueElements.add(this);
	            }
	        }
	        else {
	            queueElements.add(this);
	        }
	    }
	    addToTransparentRenderQueue(context, queue) {
	        var subMeshStaticBatch = this.staticBatch;
	        var queueElements = queue.elements;
	        var elements = queueElements.elements;
	        if (subMeshStaticBatch) {
	            var staManager = ILaya3D.MeshRenderStaticBatchManager.instance;
	            var staLastElement = queue.lastTransparentRenderElement;
	            if (staLastElement) {
	                var staLastRender = staLastElement.render;
	                if (staLastElement._geometry._getType() !== this._geometry._getType() || staLastElement.staticBatch !== subMeshStaticBatch || staLastElement.material !== this.material || staLastRender.receiveShadow !== this.render.receiveShadow || staLastRender.lightmapIndex !== this.render.lightmapIndex) {
	                    queueElements.add(this);
	                    queue.lastTransparentBatched = false;
	                }
	                else {
	                    if (queue.lastTransparentBatched) {
	                        elements[queueElements.length - 1].staticBatchElementList.add((this));
	                    }
	                    else {
	                        var staBatchElement = staManager._getBatchRenderElementFromPool();
	                        staBatchElement.renderType = RenderElement.RENDERTYPE_STATICBATCH;
	                        staBatchElement.setGeometry(subMeshStaticBatch);
	                        staBatchElement.material = staLastElement.material;
	                        var staRootOwner = subMeshStaticBatch.batchOwner;
	                        var staBatchTransform = staRootOwner ? staRootOwner._transform : null;
	                        staBatchElement.setTransform(staBatchTransform);
	                        staBatchElement.render = this.render;
	                        staBatchElement.renderSubShader = staLastElement.renderSubShader;
	                        var staBatchList = staBatchElement.staticBatchElementList;
	                        staBatchList.length = 0;
	                        staBatchList.add(staLastElement);
	                        staBatchList.add(this);
	                        elements[queueElements.length - 1] = staBatchElement;
	                    }
	                    queue.lastTransparentBatched = true;
	                }
	            }
	            else {
	                queueElements.add(this);
	                queue.lastTransparentBatched = false;
	            }
	        }
	        else if (this.renderSubShader._owner._enableInstancing && Laya.LayaGL.layaGPUInstance.supportInstance() && this.render.lightmapIndex < 0) {
	            var subMesh = this._geometry;
	            var insManager = ILaya3D.MeshRenderDynamicBatchManager.instance;
	            var insLastElement = queue.lastTransparentRenderElement;
	            if (insLastElement) {
	                var insLastRender = insLastElement.render;
	                if (insLastElement._geometry._getType() !== this._geometry._getType() || insLastElement._geometry !== subMesh || insLastElement.material !== this.material || insLastRender.receiveShadow !== this.render.receiveShadow) {
	                    queueElements.add(this);
	                    queue.lastTransparentBatched = false;
	                }
	                else {
	                    if (queue.lastTransparentBatched) {
	                        var instanceBatchElementList = elements[queueElements.length - 1].instanceBatchElementList;
	                        if (instanceBatchElementList.length === SubMeshInstanceBatch.instance.maxInstanceCount) {
	                            queueElements.add(this);
	                            queue.lastTransparentBatched = false;
	                        }
	                        else {
	                            instanceBatchElementList.add(this);
	                            queue.lastTransparentBatched = true;
	                        }
	                    }
	                    else {
	                        var insBatchElement = insManager._getBatchRenderElementFromPool();
	                        insBatchElement.renderType = RenderElement.RENDERTYPE_INSTANCEBATCH;
	                        insBatchElement.setGeometry(SubMeshInstanceBatch.instance);
	                        insBatchElement.material = insLastElement.material;
	                        insBatchElement.setTransform(null);
	                        insBatchElement.render = this.render;
	                        insBatchElement.instanceSubMesh = subMesh;
	                        insBatchElement.renderSubShader = insLastElement.renderSubShader;
	                        var insBatchList = insBatchElement.instanceBatchElementList;
	                        insBatchList.length = 0;
	                        insBatchList.add(insLastElement);
	                        insBatchList.add(this);
	                        elements[queueElements.length - 1] = insBatchElement;
	                        queue.lastTransparentBatched = true;
	                    }
	                }
	            }
	            else {
	                queueElements.add(this);
	                queue.lastTransparentBatched = false;
	            }
	        }
	        else if (this._dynamicVertexBatch) {
	            var verDec = this._geometry._vertexBuffer.vertexDeclaration;
	            var dynManager = ILaya3D.MeshRenderDynamicBatchManager.instance;
	            var dynLastElement = queue.lastTransparentRenderElement;
	            if (dynLastElement) {
	                var dynLastRender = dynLastElement.render;
	                if (dynLastElement._geometry._getType() !== this._geometry._getType() || dynLastElement._geometry._vertexBuffer._vertexDeclaration !== verDec || dynLastElement.material !== this.material || dynLastRender.receiveShadow !== this.render.receiveShadow || dynLastRender.lightmapIndex !== this.render.lightmapIndex) {
	                    queueElements.add(this);
	                    queue.lastTransparentBatched = false;
	                }
	                else {
	                    if (queue.lastTransparentBatched) {
	                        elements[queueElements.length - 1].vertexBatchElementList.add((this));
	                    }
	                    else {
	                        var dynBatchElement = dynManager._getBatchRenderElementFromPool();
	                        dynBatchElement.renderType = RenderElement.RENDERTYPE_VERTEXBATCH;
	                        dynBatchElement.setGeometry(ILaya3D.SubMeshDynamicBatch.instance);
	                        dynBatchElement.material = dynLastElement.material;
	                        dynBatchElement.setTransform(null);
	                        dynBatchElement.render = this.render;
	                        dynBatchElement.vertexBatchVertexDeclaration = verDec;
	                        dynBatchElement.renderSubShader = dynLastElement.renderSubShader;
	                        var dynBatchList = dynBatchElement.vertexBatchElementList;
	                        dynBatchList.length = 0;
	                        dynBatchList.add(dynLastElement);
	                        dynBatchList.add(this);
	                        elements[queueElements.length - 1] = dynBatchElement;
	                    }
	                    queue.lastTransparentBatched = true;
	                }
	            }
	            else {
	                queueElements.add(this);
	                queue.lastTransparentBatched = false;
	            }
	        }
	        else {
	            queueElements.add(this);
	        }
	        queue.lastTransparentRenderElement = this;
	    }
	    getInvertFront() {
	        switch (this.renderType) {
	            case RenderElement.RENDERTYPE_NORMAL:
	                return this._transform._isFrontFaceInvert;
	            case RenderElement.RENDERTYPE_STATICBATCH:
	            case RenderElement.RENDERTYPE_VERTEXBATCH:
	                return false;
	            case RenderElement.RENDERTYPE_INSTANCEBATCH:
	                return this.instanceBatchElementList.elements[0]._transform._isFrontFaceInvert;
	            default:
	                throw "SubMeshRenderElement: unknown renderType";
	        }
	    }
	    destroy() {
	        super.destroy();
	        this._dynamicWorldPositions = null;
	        this._dynamicWorldNormals = null;
	        this.staticBatch = null;
	        this.staticBatchElementList = null;
	        this.vertexBatchElementList = null;
	        this.vertexBatchVertexDeclaration = null;
	    }
	}

	class SubMeshStaticBatch extends GeometryElement {
	    constructor(batchOwner, vertexDeclaration) {
	        super();
	        this._bufferState = new BufferState();
	        this._batchID = SubMeshStaticBatch._batchIDCounter++;
	        this._batchElements = [];
	        this._currentBatchVertexCount = 0;
	        this._currentBatchIndexCount = 0;
	        this._vertexDeclaration = vertexDeclaration;
	        this.batchOwner = batchOwner;
	    }
	    _getStaticBatchBakedVertexs(batchVertices, batchOffset, batchOwnerTransform, transform, render, mesh) {
	        var vertexBuffer = mesh._vertexBuffer;
	        var vertexDeclaration = vertexBuffer.vertexDeclaration;
	        var positionOffset = vertexDeclaration.getVertexElementByUsage(VertexMesh.MESH_POSITION0)._offset / 4;
	        var normalElement = vertexDeclaration.getVertexElementByUsage(VertexMesh.MESH_NORMAL0);
	        var normalOffset = normalElement ? normalElement._offset / 4 : -1;
	        var colorElement = vertexDeclaration.getVertexElementByUsage(VertexMesh.MESH_COLOR0);
	        var colorOffset = colorElement ? colorElement._offset / 4 : -1;
	        var uv0Element = vertexDeclaration.getVertexElementByUsage(VertexMesh.MESH_TEXTURECOORDINATE0);
	        var uv0Offset = uv0Element ? uv0Element._offset / 4 : -1;
	        var uv1Element = vertexDeclaration.getVertexElementByUsage(VertexMesh.MESH_TEXTURECOORDINATE1);
	        var uv1Offset = uv1Element ? uv1Element._offset / 4 : -1;
	        var tangentElement = vertexDeclaration.getVertexElementByUsage(VertexMesh.MESH_TANGENT0);
	        var sTangentOffset = tangentElement ? tangentElement._offset / 4 : -1;
	        var bakeVertexFloatCount = 18;
	        var oriVertexFloatCount = vertexDeclaration.vertexStride / 4;
	        var oriVertexes = vertexBuffer.getFloat32Data();
	        var worldMat;
	        if (batchOwnerTransform) {
	            var rootMat = batchOwnerTransform.worldMatrix;
	            rootMat.invert(SubMeshStaticBatch._tempMatrix4x40);
	            worldMat = SubMeshStaticBatch._tempMatrix4x41;
	            Matrix4x4.multiply(SubMeshStaticBatch._tempMatrix4x40, transform.worldMatrix, worldMat);
	        }
	        else {
	            worldMat = transform.worldMatrix;
	        }
	        var rotation = SubMeshStaticBatch._tempQuaternion0;
	        worldMat.decomposeTransRotScale(SubMeshStaticBatch._tempVector30, rotation, SubMeshStaticBatch._tempVector31);
	        var lightmapScaleOffset = render.lightmapScaleOffset;
	        var vertexCount = mesh.vertexCount;
	        for (var i = 0; i < vertexCount; i++) {
	            var oriOffset = i * oriVertexFloatCount;
	            var bakeOffset = (i + batchOffset) * bakeVertexFloatCount;
	            Utils3D.transformVector3ArrayToVector3ArrayCoordinate(oriVertexes, oriOffset + positionOffset, worldMat, batchVertices, bakeOffset + 0);
	            if (normalOffset !== -1)
	                Utils3D.transformVector3ArrayByQuat(oriVertexes, oriOffset + normalOffset, rotation, batchVertices, bakeOffset + 3);
	            var j, m;
	            var bakOff = bakeOffset + 6;
	            if (colorOffset !== -1) {
	                var oriOff = oriOffset + colorOffset;
	                for (j = 0, m = 4; j < m; j++)
	                    batchVertices[bakOff + j] = oriVertexes[oriOff + j];
	            }
	            else {
	                for (j = 0, m = 4; j < m; j++)
	                    batchVertices[bakOff + j] = 1.0;
	            }
	            if (uv0Offset !== -1) {
	                var absUv0Offset = oriOffset + uv0Offset;
	                batchVertices[bakeOffset + 10] = oriVertexes[absUv0Offset];
	                batchVertices[bakeOffset + 11] = oriVertexes[absUv0Offset + 1];
	            }
	            if (lightmapScaleOffset) {
	                if (uv1Offset !== -1)
	                    Utils3D.transformLightingMapTexcoordArray(oriVertexes, oriOffset + uv1Offset, lightmapScaleOffset, batchVertices, bakeOffset + 12);
	                else
	                    Utils3D.transformLightingMapTexcoordArray(oriVertexes, oriOffset + uv0Offset, lightmapScaleOffset, batchVertices, bakeOffset + 12);
	            }
	            if (sTangentOffset !== -1) {
	                var absSTanegntOffset = oriOffset + sTangentOffset;
	                batchVertices[bakeOffset + 14] = oriVertexes[absSTanegntOffset];
	                batchVertices[bakeOffset + 15] = oriVertexes[absSTanegntOffset + 1];
	                batchVertices[bakeOffset + 16] = oriVertexes[absSTanegntOffset + 2];
	                batchVertices[bakeOffset + 17] = oriVertexes[absSTanegntOffset + 3];
	            }
	        }
	        return vertexCount;
	    }
	    addTest(sprite) {
	        var vertexCount;
	        var subMeshVertexCount = sprite.meshFilter.sharedMesh.vertexCount;
	        vertexCount = this._currentBatchVertexCount + subMeshVertexCount;
	        if (vertexCount > SubMeshStaticBatch.maxBatchVertexCount)
	            return false;
	        return true;
	    }
	    add(sprite) {
	        var mesh = sprite.meshFilter.sharedMesh;
	        var subMeshVertexCount = mesh.vertexCount;
	        this._batchElements.push(sprite);
	        var render = sprite._render;
	        render._isPartOfStaticBatch = true;
	        render._staticBatch = this;
	        var renderElements = render._renderElements;
	        for (var i = 0, n = renderElements.length; i < n; i++)
	            renderElements[i].staticBatch = this;
	        this._currentBatchIndexCount += mesh._indexBuffer.indexCount;
	        this._currentBatchVertexCount += subMeshVertexCount;
	    }
	    remove(sprite) {
	        var mesh = sprite.meshFilter.sharedMesh;
	        var index = this._batchElements.indexOf(sprite);
	        if (index !== -1) {
	            this._batchElements.splice(index, 1);
	            var renderElements = sprite._render._renderElements;
	            for (var i = 0, n = renderElements.length; i < n; i++)
	                renderElements[i].staticBatch = null;
	            this._currentBatchIndexCount = this._currentBatchIndexCount - mesh._indexBuffer.indexCount;
	            this._currentBatchVertexCount = this._currentBatchVertexCount - mesh.vertexCount;
	            sprite._render._isPartOfStaticBatch = false;
	        }
	    }
	    finishInit() {
	        if (this._vertexBuffer) {
	            this._vertexBuffer.destroy();
	            this._indexBuffer.destroy();
	            Laya.Resource._addGPUMemory(-(this._vertexBuffer._byteLength + this._indexBuffer._byteLength));
	        }
	        var gl = Laya.LayaGL.instance;
	        var batchVertexCount = 0;
	        var batchIndexCount = 0;
	        var rootOwner = this.batchOwner;
	        var floatStride = this._vertexDeclaration.vertexStride / 4;
	        var vertexDatas = new Float32Array(floatStride * this._currentBatchVertexCount);
	        var indexDatas = new Uint16Array(this._currentBatchIndexCount);
	        this._vertexBuffer = new VertexBuffer3D(this._vertexDeclaration.vertexStride * this._currentBatchVertexCount, gl.STATIC_DRAW);
	        this._vertexBuffer.vertexDeclaration = this._vertexDeclaration;
	        this._indexBuffer = new IndexBuffer3D(IndexBuffer3D.INDEXTYPE_USHORT, this._currentBatchIndexCount, gl.STATIC_DRAW);
	        for (var i = 0, n = this._batchElements.length; i < n; i++) {
	            var sprite = this._batchElements[i];
	            var mesh = sprite.meshFilter.sharedMesh;
	            var meshVerCount = this._getStaticBatchBakedVertexs(vertexDatas, batchVertexCount, rootOwner ? rootOwner._transform : null, sprite._transform, sprite._render, mesh);
	            var indices = mesh._indexBuffer.getData();
	            var indexOffset = batchVertexCount;
	            var indexEnd = batchIndexCount + indices.length;
	            var elements = sprite._render._renderElements;
	            for (var j = 0, m = mesh.subMeshCount; j < m; j++) {
	                var subMesh = mesh._subMeshes[j];
	                var start = batchIndexCount + subMesh._indexStart;
	                var element = elements[j];
	                element.staticBatchIndexStart = start;
	                element.staticBatchIndexEnd = start + subMesh._indexCount;
	            }
	            indexDatas.set(indices, batchIndexCount);
	            var k;
	            var isInvert = rootOwner ? (sprite._transform._isFrontFaceInvert !== rootOwner.transform._isFrontFaceInvert) : sprite._transform._isFrontFaceInvert;
	            if (isInvert) {
	                for (k = batchIndexCount; k < indexEnd; k += 3) {
	                    indexDatas[k] = indexOffset + indexDatas[k];
	                    var index1 = indexDatas[k + 1];
	                    var index2 = indexDatas[k + 2];
	                    indexDatas[k + 1] = indexOffset + index2;
	                    indexDatas[k + 2] = indexOffset + index1;
	                }
	            }
	            else {
	                for (k = batchIndexCount; k < indexEnd; k += 3) {
	                    indexDatas[k] = indexOffset + indexDatas[k];
	                    indexDatas[k + 1] = indexOffset + indexDatas[k + 1];
	                    indexDatas[k + 2] = indexOffset + indexDatas[k + 2];
	                }
	            }
	            batchIndexCount += indices.length;
	            batchVertexCount += meshVerCount;
	        }
	        this._vertexBuffer.setData(vertexDatas.buffer);
	        this._indexBuffer.setData(indexDatas);
	        var memorySize = this._vertexBuffer._byteLength + this._indexBuffer._byteLength;
	        Laya.Resource._addGPUMemory(memorySize);
	        this._bufferState.bind();
	        this._bufferState.applyVertexBuffer(this._vertexBuffer);
	        this._bufferState.applyIndexBuffer(this._indexBuffer);
	        this._bufferState.unBind();
	    }
	    _render(state) {
	        this._bufferState.bind();
	        var gl = Laya.LayaGL.instance;
	        var element = state.renderElement;
	        var staticBatchElementList = element.staticBatchElementList;
	        var batchElementList = staticBatchElementList.elements;
	        var from = 0;
	        var end = 0;
	        var count = staticBatchElementList.length;
	        for (var i = 1; i < count; i++) {
	            var lastElement = batchElementList[i - 1];
	            if (lastElement.staticBatchIndexEnd === batchElementList[i].staticBatchIndexStart) {
	                end++;
	                continue;
	            }
	            else {
	                var start = batchElementList[from].staticBatchIndexStart;
	                var indexCount = batchElementList[end].staticBatchIndexEnd - start;
	                gl.drawElements(gl.TRIANGLES, indexCount, gl.UNSIGNED_SHORT, start * 2);
	                from = ++end;
	                Laya.Stat.trianglesFaces += indexCount / 3;
	            }
	        }
	        start = batchElementList[from].staticBatchIndexStart;
	        indexCount = batchElementList[end].staticBatchIndexEnd - start;
	        gl.drawElements(gl.TRIANGLES, indexCount, gl.UNSIGNED_SHORT, start * 2);
	        Laya.Stat.renderBatches++;
	        Laya.Stat.savedRenderBatches += count - 1;
	        Laya.Stat.trianglesFaces += indexCount / 3;
	    }
	    dispose() {
	        var memorySize = this._vertexBuffer._byteLength + this._indexBuffer._byteLength;
	        Laya.Resource._addGPUMemory(-memorySize);
	        this._batchElements = null;
	        this.batchOwner = null;
	        this._vertexDeclaration = null;
	        this._bufferState.destroy();
	        this._vertexBuffer.destroy();
	        this._indexBuffer.destroy();
	        this._vertexBuffer = null;
	        this._indexBuffer = null;
	        this._bufferState = null;
	    }
	}
	SubMeshStaticBatch._tempVector30 = new Vector3();
	SubMeshStaticBatch._tempVector31 = new Vector3();
	SubMeshStaticBatch._tempQuaternion0 = new Quaternion();
	SubMeshStaticBatch._tempMatrix4x40 = new Matrix4x4();
	SubMeshStaticBatch._tempMatrix4x41 = new Matrix4x4();
	SubMeshStaticBatch.maxBatchVertexCount = 65535;
	SubMeshStaticBatch._batchIDCounter = 0;

	class SingletonList {
	    constructor() {
	        this.elements = [];
	        this.length = 0;
	    }
	    _add(element) {
	        if (this.length === this.elements.length)
	            this.elements.push(element);
	        else
	            this.elements[this.length] = element;
	    }
	    add(element) {
	        if (this.length === this.elements.length)
	            this.elements.push(element);
	        else
	            this.elements[this.length] = element;
	        this.length++;
	    }
	}

	class MeshRenderStaticBatchManager extends StaticBatchManager {
	    constructor() {
	        super();
	        this._opaqueBatchMarks = [];
	        this._updateCountMark = 0;
	    }
	    static __init__() {
	        MeshRenderStaticBatchManager._verDec = VertexMesh.getVertexDeclaration("POSITION,NORMAL,COLOR,UV,UV1,TANGENT");
	    }
	    _compare(left, right) {
	        var lRender = left._render, rRender = right._render;
	        var leftGeo = left.meshFilter.sharedMesh, rightGeo = right.meshFilter.sharedMesh;
	        var lightOffset = lRender.lightmapIndex - rRender.lightmapIndex;
	        if (lightOffset === 0) {
	            var receiveShadowOffset = (lRender.receiveShadow ? 1 : 0) - (rRender.receiveShadow ? 1 : 0);
	            if (receiveShadowOffset === 0) {
	                var materialOffset = (lRender.sharedMaterial && rRender.sharedMaterial) ? lRender.sharedMaterial.id - rRender.sharedMaterial.id : 0;
	                if (materialOffset === 0) {
	                    var verDec = leftGeo._vertexBuffer.vertexDeclaration.id - rightGeo._vertexBuffer.vertexDeclaration.id;
	                    if (verDec === 0) {
	                        return rightGeo._indexBuffer.indexCount - leftGeo._indexBuffer.indexCount;
	                    }
	                    else {
	                        return verDec;
	                    }
	                }
	                else {
	                    return materialOffset;
	                }
	            }
	            else {
	                return receiveShadowOffset;
	            }
	        }
	        else {
	            return lightOffset;
	        }
	    }
	    _getBatchRenderElementFromPool() {
	        var renderElement = this._batchRenderElementPool[this._batchRenderElementPoolIndex++];
	        if (!renderElement) {
	            renderElement = new SubMeshRenderElement();
	            this._batchRenderElementPool[this._batchRenderElementPoolIndex - 1] = renderElement;
	            renderElement.staticBatchElementList = new SingletonList();
	        }
	        return renderElement;
	    }
	    _getStaticBatch(staticBatches, rootOwner, number) {
	        var subMeshStaticBatch = staticBatches[number];
	        if (!subMeshStaticBatch) {
	            subMeshStaticBatch = staticBatches[number] = new SubMeshStaticBatch(rootOwner, MeshRenderStaticBatchManager._verDec);
	            this._staticBatches[subMeshStaticBatch._batchID] = subMeshStaticBatch;
	        }
	        return subMeshStaticBatch;
	    }
	    _initStaticBatchs(rootOwner) {
	        var initBatchSprites = this._initBatchSprites;
	        this._quickSort(initBatchSprites, 0, initBatchSprites.length - 1);
	        var staticBatches = [];
	        var lastCanMerage = false;
	        var curStaticBatch;
	        var batchNumber = 0;
	        for (var i = 0, n = initBatchSprites.length; i < n; i++) {
	            var sprite = initBatchSprites[i];
	            if (lastCanMerage) {
	                if (curStaticBatch.addTest(sprite)) {
	                    curStaticBatch.add(sprite);
	                }
	                else {
	                    lastCanMerage = false;
	                    batchNumber++;
	                }
	            }
	            else {
	                var lastIndex = n - 1;
	                if (i !== lastIndex) {
	                    curStaticBatch = this._getStaticBatch(staticBatches, rootOwner, batchNumber);
	                    curStaticBatch.add(sprite);
	                    lastCanMerage = true;
	                }
	            }
	        }
	        for (i = 0, n = staticBatches.length; i < n; i++) {
	            var staticBatch = staticBatches[i];
	            staticBatch && staticBatch.finishInit();
	        }
	        this._initBatchSprites.length = 0;
	    }
	    _removeRenderSprite(sprite) {
	        var render = sprite._render;
	        var staticBatch = render._staticBatch;
	        var batchElements = staticBatch._batchElements;
	        var index = batchElements.indexOf(sprite);
	        if (index !== -1) {
	            batchElements.splice(index, 1);
	            render._staticBatch = null;
	            var renderElements = render._renderElements;
	            for (var i = 0, n = renderElements.length; i < n; i++)
	                renderElements[i].staticBatch = null;
	        }
	        if (batchElements.length === 0) {
	            delete this._staticBatches[staticBatch._batchID];
	            staticBatch.dispose();
	        }
	    }
	    _clear() {
	        super._clear();
	        this._updateCountMark++;
	    }
	    _garbageCollection() {
	        for (var key in this._staticBatches) {
	            var staticBatch = this._staticBatches[key];
	            if (staticBatch._batchElements.length === 0) {
	                staticBatch.dispose();
	                delete this._staticBatches[key];
	            }
	        }
	    }
	    getBatchOpaquaMark(lightMapIndex, receiveShadow, materialID, staticBatchID) {
	        var receiveShadowIndex = receiveShadow ? 1 : 0;
	        var staLightMapMarks = (this._opaqueBatchMarks[lightMapIndex]) || (this._opaqueBatchMarks[lightMapIndex] = []);
	        var staReceiveShadowMarks = (staLightMapMarks[receiveShadowIndex]) || (staLightMapMarks[receiveShadowIndex] = []);
	        var staMaterialMarks = (staReceiveShadowMarks[materialID]) || (staReceiveShadowMarks[materialID] = []);
	        return (staMaterialMarks[staticBatchID]) || (staMaterialMarks[staticBatchID] = new BatchMark);
	    }
	}
	MeshRenderStaticBatchManager.instance = new MeshRenderStaticBatchManager();

	class MeshSprite3DShaderDeclaration {
	}

	class BoundBox {
	    constructor(min, max) {
	        this.min = min;
	        this.max = max;
	    }
	    _rotateExtents(extents, rotation, out) {
	        var extentsX = extents.x;
	        var extentsY = extents.y;
	        var extentsZ = extents.z;
	        var matElements = rotation.elements;
	        out.x = Math.abs(matElements[0] * extentsX) + Math.abs(matElements[4] * extentsY) + Math.abs(matElements[8] * extentsZ);
	        out.y = Math.abs(matElements[1] * extentsX) + Math.abs(matElements[5] * extentsY) + Math.abs(matElements[9] * extentsZ);
	        out.z = Math.abs(matElements[2] * extentsX) + Math.abs(matElements[6] * extentsY) + Math.abs(matElements[10] * extentsZ);
	    }
	    getCorners(corners) {
	        corners.length = 8;
	        var minX = this.min.x;
	        var minY = this.min.y;
	        var minZ = this.min.z;
	        var maxX = this.max.x;
	        var maxY = this.max.y;
	        var maxZ = this.max.z;
	        corners[0] = new Vector3(minX, maxY, maxZ);
	        corners[1] = new Vector3(maxX, maxY, maxZ);
	        corners[2] = new Vector3(maxX, minY, maxZ);
	        corners[3] = new Vector3(minX, minY, maxZ);
	        corners[4] = new Vector3(minX, maxY, minZ);
	        corners[5] = new Vector3(maxX, maxY, minZ);
	        corners[6] = new Vector3(maxX, minY, minZ);
	        corners[7] = new Vector3(minX, minY, minZ);
	    }
	    getCenter(out) {
	        Vector3.add(this.min, this.max, out);
	        Vector3.scale(out, 0.5, out);
	    }
	    getExtent(out) {
	        Vector3.subtract(this.max, this.min, out);
	        Vector3.scale(out, 0.5, out);
	    }
	    setCenterAndExtent(center, extent) {
	        Vector3.subtract(center, extent, this.min);
	        Vector3.add(center, extent, this.max);
	    }
	    tranform(matrix, out) {
	        var center = BoundBox._tempVector30;
	        var extent = BoundBox._tempVector31;
	        this.getCenter(center);
	        this.getExtent(extent);
	        Vector3.transformCoordinate(center, matrix, center);
	        this._rotateExtents(extent, matrix, extent);
	        out.setCenterAndExtent(center, extent);
	    }
	    toDefault() {
	        this.min.toDefault();
	        this.max.toDefault();
	    }
	    static createfromPoints(points, out) {
	        if (points == null)
	            throw new Error("points");
	        var min = out.min;
	        var max = out.max;
	        min.x = Number.MAX_VALUE;
	        min.y = Number.MAX_VALUE;
	        min.z = Number.MAX_VALUE;
	        max.x = -Number.MAX_VALUE;
	        max.y = -Number.MAX_VALUE;
	        max.z = -Number.MAX_VALUE;
	        for (var i = 0, n = points.length; i < n; ++i) {
	            Vector3.min(min, points[i], min);
	            Vector3.max(max, points[i], max);
	        }
	    }
	    static merge(box1, box2, out) {
	        Vector3.min(box1.min, box2.min, out.min);
	        Vector3.max(box1.max, box2.max, out.max);
	    }
	    cloneTo(destObject) {
	        var dest = destObject;
	        this.min.cloneTo(dest.min);
	        this.max.cloneTo(dest.max);
	    }
	    clone() {
	        var dest = new BoundBox(new Vector3(), new Vector3());
	        this.cloneTo(dest);
	        return dest;
	    }
	}
	BoundBox._tempVector30 = new Vector3();
	BoundBox._tempVector31 = new Vector3();

	class Bounds {
	    constructor(min, max) {
	        this._updateFlag = 0;
	        this._center = new Vector3();
	        this._extent = new Vector3();
	        this._boundBox = new BoundBox(new Vector3(), new Vector3());
	        min.cloneTo(this._boundBox.min);
	        max.cloneTo(this._boundBox.max);
	        this._setUpdateFlag(Bounds._UPDATE_CENTER | Bounds._UPDATE_EXTENT, true);
	    }
	    setMin(value) {
	        var min = this._boundBox.min;
	        if (value !== min)
	            value.cloneTo(min);
	        this._setUpdateFlag(Bounds._UPDATE_CENTER | Bounds._UPDATE_EXTENT, true);
	        this._setUpdateFlag(Bounds._UPDATE_MIN, false);
	    }
	    getMin() {
	        var min = this._boundBox.min;
	        if (this._getUpdateFlag(Bounds._UPDATE_MIN)) {
	            this._getMin(this.getCenter(), this.getExtent(), min);
	            this._setUpdateFlag(Bounds._UPDATE_MIN, false);
	        }
	        return min;
	    }
	    setMax(value) {
	        var max = this._boundBox.max;
	        if (value !== max)
	            value.cloneTo(max);
	        this._setUpdateFlag(Bounds._UPDATE_CENTER | Bounds._UPDATE_EXTENT, true);
	        this._setUpdateFlag(Bounds._UPDATE_MAX, false);
	    }
	    getMax() {
	        var max = this._boundBox.max;
	        if (this._getUpdateFlag(Bounds._UPDATE_MAX)) {
	            this._getMax(this.getCenter(), this.getExtent(), max);
	            this._setUpdateFlag(Bounds._UPDATE_MAX, false);
	        }
	        return max;
	    }
	    setCenter(value) {
	        if (value !== this._center)
	            value.cloneTo(this._center);
	        this._setUpdateFlag(Bounds._UPDATE_MIN | Bounds._UPDATE_MAX, true);
	        this._setUpdateFlag(Bounds._UPDATE_CENTER, false);
	    }
	    getCenter() {
	        if (this._getUpdateFlag(Bounds._UPDATE_CENTER)) {
	            this._getCenter(this.getMin(), this.getMax(), this._center);
	            this._setUpdateFlag(Bounds._UPDATE_CENTER, false);
	        }
	        return this._center;
	    }
	    setExtent(value) {
	        if (value !== this._extent)
	            value.cloneTo(this._extent);
	        this._setUpdateFlag(Bounds._UPDATE_MIN | Bounds._UPDATE_MAX, true);
	        this._setUpdateFlag(Bounds._UPDATE_EXTENT, false);
	    }
	    getExtent() {
	        if (this._getUpdateFlag(Bounds._UPDATE_EXTENT)) {
	            this._getExtent(this.getMin(), this.getMax(), this._extent);
	            this._setUpdateFlag(Bounds._UPDATE_EXTENT, false);
	        }
	        return this._extent;
	    }
	    _getUpdateFlag(type) {
	        return (this._updateFlag & type) != 0;
	    }
	    _setUpdateFlag(type, value) {
	        if (value)
	            this._updateFlag |= type;
	        else
	            this._updateFlag &= ~type;
	    }
	    _getCenter(min, max, out) {
	        Vector3.add(min, max, out);
	        Vector3.scale(out, 0.5, out);
	    }
	    _getExtent(min, max, out) {
	        Vector3.subtract(max, min, out);
	        Vector3.scale(out, 0.5, out);
	    }
	    _getMin(center, extent, out) {
	        Vector3.subtract(center, extent, out);
	    }
	    _getMax(center, extent, out) {
	        Vector3.add(center, extent, out);
	    }
	    _rotateExtents(extents, rotation, out) {
	        var extentsX = extents.x;
	        var extentsY = extents.y;
	        var extentsZ = extents.z;
	        var matE = rotation.elements;
	        out.x = Math.abs(matE[0] * extentsX) + Math.abs(matE[4] * extentsY) + Math.abs(matE[8] * extentsZ);
	        out.y = Math.abs(matE[1] * extentsX) + Math.abs(matE[5] * extentsY) + Math.abs(matE[9] * extentsZ);
	        out.z = Math.abs(matE[2] * extentsX) + Math.abs(matE[6] * extentsY) + Math.abs(matE[10] * extentsZ);
	    }
	    _tranform(matrix, out) {
	        var outCen = out._center;
	        var outExt = out._extent;
	        Vector3.transformCoordinate(this.getCenter(), matrix, outCen);
	        this._rotateExtents(this.getExtent(), matrix, outExt);
	        out._boundBox.setCenterAndExtent(outCen, outExt);
	        out._updateFlag = 0;
	    }
	    _getBoundBox() {
	        if (this._updateFlag & Bounds._UPDATE_MIN) {
	            var min = this._boundBox.min;
	            this._getMin(this.getCenter(), this.getExtent(), min);
	            this._setUpdateFlag(Bounds._UPDATE_MIN, false);
	        }
	        if (this._updateFlag & Bounds._UPDATE_MAX) {
	            var max = this._boundBox.max;
	            this._getMax(this.getCenter(), this.getExtent(), max);
	            this._setUpdateFlag(Bounds._UPDATE_MAX, false);
	        }
	        return this._boundBox;
	    }
	    cloneTo(destObject) {
	        var destBounds = destObject;
	        this.getMin().cloneTo(destBounds._boundBox.min);
	        this.getMax().cloneTo(destBounds._boundBox.max);
	        this.getCenter().cloneTo(destBounds._center);
	        this.getExtent().cloneTo(destBounds._extent);
	        destBounds._updateFlag = 0;
	    }
	    clone() {
	        var dest = new Bounds(new Vector3(), new Vector3());
	        this.cloneTo(dest);
	        return dest;
	    }
	}
	Bounds._UPDATE_MIN = 0x01;
	Bounds._UPDATE_MAX = 0x02;
	Bounds._UPDATE_CENTER = 0x04;
	Bounds._UPDATE_EXTENT = 0x08;

	class BaseRender extends Laya.EventDispatcher {
	    constructor(owner) {
	        super();
	        this._indexInList = -1;
	        this._indexInCastShadowList = -1;
	        this._boundsChange = true;
	        this._supportOctree = true;
	        this._sharedMaterials = [];
	        this._visible = true;
	        this._indexInOctreeMotionList = -1;
	        this._updateMark = -1;
	        this._updateRenderType = -1;
	        this._isPartOfStaticBatch = false;
	        this._staticBatch = null;
	        this._id = ++BaseRender._uniqueIDCounter;
	        this._indexInCastShadowList = -1;
	        this._bounds = new Bounds(Vector3._ZERO, Vector3._ZERO);
	        if (Laya.Render.supportWebGLPlusCulling) {
	            var length = FrustumCulling._cullingBufferLength;
	            this._cullingBufferIndex = length;
	            var cullingBuffer = FrustumCulling._cullingBuffer;
	            var resizeLength = length + 7;
	            if (resizeLength >= cullingBuffer.length) {
	                var temp = cullingBuffer;
	                cullingBuffer = FrustumCulling._cullingBuffer = new Float32Array(cullingBuffer.length + 4096);
	                cullingBuffer.set(temp, 0);
	            }
	            cullingBuffer[length] = 2;
	            FrustumCulling._cullingBufferLength = resizeLength;
	        }
	        this._renderElements = [];
	        this._owner = owner;
	        this._enable = true;
	        this._materialsInstance = [];
	        this._shaderValues = new ShaderData(null);
	        this.lightmapIndex = -1;
	        this._castShadow = false;
	        this.receiveShadow = false;
	        this.sortingFudge = 0.0;
	        (owner) && (this._owner.transform.on(Laya.Event.TRANSFORM_CHANGED, this, this._onWorldMatNeedChange));
	    }
	    get id() {
	        return this._id;
	    }
	    get lightmapIndex() {
	        return this._lightmapIndex;
	    }
	    set lightmapIndex(value) {
	        if (this._lightmapIndex !== value) {
	            this._lightmapIndex = value;
	            this._applyLightMapParams();
	        }
	    }
	    get lightmapScaleOffset() {
	        return this._lightmapScaleOffset;
	    }
	    set lightmapScaleOffset(value) {
	        this._lightmapScaleOffset = value;
	        this._shaderValues.setVector(RenderableSprite3D.LIGHTMAPSCALEOFFSET, value);
	        this._shaderValues.addDefine(RenderableSprite3D.SHADERDEFINE_SCALEOFFSETLIGHTINGMAPUV);
	    }
	    get enable() {
	        return this._enable;
	    }
	    set enable(value) {
	        this._enable = !!value;
	    }
	    get material() {
	        var material = this._sharedMaterials[0];
	        if (material && !this._materialsInstance[0]) {
	            var insMat = this._getInstanceMaterial(material, 0);
	            var renderElement = this._renderElements[0];
	            (renderElement) && (renderElement.material = insMat);
	        }
	        return this._sharedMaterials[0];
	    }
	    set material(value) {
	        this.sharedMaterial = value;
	    }
	    get materials() {
	        for (var i = 0, n = this._sharedMaterials.length; i < n; i++) {
	            if (!this._materialsInstance[i]) {
	                var insMat = this._getInstanceMaterial(this._sharedMaterials[i], i);
	                var renderElement = this._renderElements[i];
	                (renderElement) && (renderElement.material = insMat);
	            }
	        }
	        return this._sharedMaterials.slice();
	    }
	    set materials(value) {
	        this.sharedMaterials = value;
	    }
	    get sharedMaterial() {
	        return this._sharedMaterials[0];
	    }
	    set sharedMaterial(value) {
	        var lastValue = this._sharedMaterials[0];
	        if (lastValue !== value) {
	            this._sharedMaterials[0] = value;
	            this._materialsInstance[0] = false;
	            this._changeMaterialReference(lastValue, value);
	            var renderElement = this._renderElements[0];
	            (renderElement) && (renderElement.material = value);
	        }
	    }
	    get sharedMaterials() {
	        return this._sharedMaterials.slice();
	    }
	    set sharedMaterials(value) {
	        var materialsInstance = this._materialsInstance;
	        var sharedMats = this._sharedMaterials;
	        for (var i = 0, n = sharedMats.length; i < n; i++) {
	            var lastMat = sharedMats[i];
	            (lastMat) && (lastMat._removeReference());
	        }
	        if (value) {
	            var count = value.length;
	            materialsInstance.length = count;
	            sharedMats.length = count;
	            for (i = 0; i < count; i++) {
	                lastMat = sharedMats[i];
	                var mat = value[i];
	                if (lastMat !== mat) {
	                    materialsInstance[i] = false;
	                    var renderElement = this._renderElements[i];
	                    (renderElement) && (renderElement.material = mat);
	                }
	                if (mat) {
	                    mat._addReference();
	                }
	                sharedMats[i] = mat;
	            }
	        }
	        else {
	            throw new Error("BaseRender: shadredMaterials value can't be null.");
	        }
	    }
	    get bounds() {
	        if (this._boundsChange) {
	            this._calculateBoundingBox();
	            this._boundsChange = false;
	        }
	        return this._bounds;
	    }
	    set receiveShadow(value) {
	        if (this._receiveShadow !== value) {
	            this._receiveShadow = value;
	            if (value)
	                this._shaderValues.addDefine(RenderableSprite3D.SHADERDEFINE_RECEIVE_SHADOW);
	            else
	                this._shaderValues.removeDefine(RenderableSprite3D.SHADERDEFINE_RECEIVE_SHADOW);
	        }
	    }
	    get receiveShadow() {
	        return this._receiveShadow;
	    }
	    get castShadow() {
	        return this._castShadow;
	    }
	    set castShadow(value) {
	        if (this._castShadow !== value) {
	            if (this._owner.activeInHierarchy) {
	                if (value)
	                    this._scene._addShadowCastRenderObject(this);
	                else
	                    this._scene._removeShadowCastRenderObject(this);
	            }
	            this._castShadow = value;
	        }
	    }
	    get isPartOfStaticBatch() {
	        return this._isPartOfStaticBatch;
	    }
	    _getOctreeNode() {
	        return this._octreeNode;
	    }
	    _setOctreeNode(value) {
	        this._octreeNode = value;
	    }
	    _getIndexInMotionList() {
	        return this._indexInOctreeMotionList;
	    }
	    _setIndexInMotionList(value) {
	        this._indexInOctreeMotionList = value;
	    }
	    _changeMaterialReference(lastValue, value) {
	        (lastValue) && (lastValue._removeReference());
	        value._addReference();
	    }
	    _getInstanceMaterial(material, index) {
	        var insMat = material.clone();
	        insMat.name = insMat.name + "(Instance)";
	        this._materialsInstance[index] = true;
	        this._changeMaterialReference(this._sharedMaterials[index], insMat);
	        this._sharedMaterials[index] = insMat;
	        return insMat;
	    }
	    _applyLightMapParams() {
	        if (this._scene && this._lightmapIndex >= 0) {
	            var lightMaps = this._scene.getlightmaps();
	            if (this._lightmapIndex < lightMaps.length) {
	                this._shaderValues.addDefine(RenderableSprite3D.SAHDERDEFINE_LIGHTMAP);
	                this._shaderValues.setTexture(RenderableSprite3D.LIGHTMAP, lightMaps[this._lightmapIndex]);
	            }
	            else {
	                this._shaderValues.removeDefine(RenderableSprite3D.SAHDERDEFINE_LIGHTMAP);
	            }
	        }
	        else {
	            this._shaderValues.removeDefine(RenderableSprite3D.SAHDERDEFINE_LIGHTMAP);
	        }
	    }
	    _onWorldMatNeedChange(flag) {
	        this._boundsChange = true;
	        if (this._octreeNode) {
	            flag &= Transform3D.TRANSFORM_WORLDPOSITION | Transform3D.TRANSFORM_WORLDQUATERNION | Transform3D.TRANSFORM_WORLDSCALE;
	            if (flag) {
	                if (this._indexInOctreeMotionList === -1)
	                    this._octreeNode._octree.addMotionObject(this);
	            }
	        }
	    }
	    _calculateBoundingBox() {
	        throw ("BaseRender: must override it.");
	    }
	    _getIndexInList() {
	        return this._indexInList;
	    }
	    _setIndexInList(index) {
	        this._indexInList = index;
	    }
	    _setBelongScene(scene) {
	        if (this._scene !== scene) {
	            this._scene = scene;
	            this._applyLightMapParams();
	        }
	    }
	    _needRender(boundFrustum, context) {
	        return true;
	    }
	    _renderUpdate(context, transform) {
	    }
	    _renderUpdateWithCamera(context, transform) {
	    }
	    _revertBatchRenderUpdate(context) {
	    }
	    _destroy() {
	        (this._indexInOctreeMotionList !== -1) && (this._octreeNode._octree.removeMotionObject(this));
	        this.offAll();
	        var i = 0, n = 0;
	        for (i = 0, n = this._renderElements.length; i < n; i++)
	            this._renderElements[i].destroy();
	        for (i = 0, n = this._sharedMaterials.length; i < n; i++)
	            (this._sharedMaterials[i].destroyed) || (this._sharedMaterials[i]._removeReference());
	        this._renderElements = null;
	        this._owner = null;
	        this._sharedMaterials = null;
	        this._bounds = null;
	        this._lightmapScaleOffset = null;
	    }
	    markAsUnStatic() {
	        if (this._isPartOfStaticBatch) {
	            MeshRenderStaticBatchManager.instance._removeRenderSprite(this._owner);
	            this._isPartOfStaticBatch = false;
	        }
	    }
	}
	BaseRender._tempBoundBoxCorners = [new Vector3(), new Vector3(), new Vector3(), new Vector3(), new Vector3(), new Vector3(), new Vector3(), new Vector3()];
	BaseRender._uniqueIDCounter = 0;

	class MeshRenderer extends BaseRender {
	    constructor(owner) {
	        super(owner);
	        this._revertStaticBatchDefineUV1 = false;
	        this._revertStaticBatchDefineLightMapUV = false;
	        this._projectionViewWorldMatrix = new Matrix4x4();
	    }
	    _createRenderElement() {
	        return new SubMeshRenderElement();
	    }
	    _onMeshChange(mesh) {
	        if (mesh) {
	            var count = mesh.subMeshCount;
	            this._renderElements.length = count;
	            for (var i = 0; i < count; i++) {
	                var renderElement = this._renderElements[i];
	                if (!renderElement) {
	                    var material = this.sharedMaterials[i];
	                    renderElement = this._renderElements[i] = this._createRenderElement();
	                    renderElement.setTransform(this._owner._transform);
	                    renderElement.render = this;
	                    renderElement.material = material ? material : BlinnPhongMaterial.defaultMaterial;
	                }
	                renderElement.setGeometry(mesh.getSubMesh(i));
	            }
	        }
	        else {
	            this._renderElements.length = 0;
	        }
	        this._boundsChange = true;
	    }
	    _calculateBoundingBox() {
	        var sharedMesh = this._owner.meshFilter.sharedMesh;
	        if (sharedMesh) {
	            var worldMat = this._owner.transform.worldMatrix;
	            sharedMesh.bounds._tranform(worldMat, this._bounds);
	        }
	        if (Laya.Render.supportWebGLPlusCulling) {
	            var min = this._bounds.getMin();
	            var max = this._bounds.getMax();
	            var buffer = FrustumCulling._cullingBuffer;
	            buffer[this._cullingBufferIndex + 1] = min.x;
	            buffer[this._cullingBufferIndex + 2] = min.y;
	            buffer[this._cullingBufferIndex + 3] = min.z;
	            buffer[this._cullingBufferIndex + 4] = max.x;
	            buffer[this._cullingBufferIndex + 5] = max.y;
	            buffer[this._cullingBufferIndex + 6] = max.z;
	        }
	    }
	    _needRender(boundFrustum, context) {
	        if (boundFrustum)
	            return boundFrustum.intersects(this.bounds._getBoundBox());
	        else
	            return true;
	    }
	    _renderUpdate(context, transform) {
	        var element = context.renderElement;
	        switch (element.renderType) {
	            case RenderElement.RENDERTYPE_NORMAL:
	                this._shaderValues.setMatrix4x4(Sprite3D.WORLDMATRIX, transform.worldMatrix);
	                break;
	            case RenderElement.RENDERTYPE_STATICBATCH:
	                if (transform)
	                    this._shaderValues.setMatrix4x4(Sprite3D.WORLDMATRIX, transform.worldMatrix);
	                else
	                    this._shaderValues.setMatrix4x4(Sprite3D.WORLDMATRIX, Matrix4x4.DEFAULT);
	                if (!this._shaderValues.hasDefine(MeshSprite3DShaderDeclaration.SHADERDEFINE_UV1)) {
	                    this._shaderValues.addDefine(MeshSprite3DShaderDeclaration.SHADERDEFINE_UV1);
	                    this._revertStaticBatchDefineUV1 = true;
	                }
	                else {
	                    this._revertStaticBatchDefineUV1 = false;
	                }
	                if (this._shaderValues.hasDefine(RenderableSprite3D.SHADERDEFINE_SCALEOFFSETLIGHTINGMAPUV)) {
	                    this._shaderValues.removeDefine(RenderableSprite3D.SHADERDEFINE_SCALEOFFSETLIGHTINGMAPUV);
	                    this._revertStaticBatchDefineLightMapUV = true;
	                }
	                else {
	                    this._revertStaticBatchDefineLightMapUV = false;
	                }
	                break;
	            case RenderElement.RENDERTYPE_VERTEXBATCH:
	                this._shaderValues.setMatrix4x4(Sprite3D.WORLDMATRIX, Matrix4x4.DEFAULT);
	                break;
	            case RenderElement.RENDERTYPE_INSTANCEBATCH:
	                var worldMatrixData = SubMeshInstanceBatch.instance.instanceWorldMatrixData;
	                var insBatches = element.instanceBatchElementList;
	                var elements = insBatches.elements;
	                var count = insBatches.length;
	                for (var i = 0; i < count; i++)
	                    worldMatrixData.set(elements[i]._transform.worldMatrix.elements, i * 16);
	                SubMeshInstanceBatch.instance.instanceWorldMatrixBuffer.setData(worldMatrixData.buffer, 0, 0, count * 16 * 4);
	                this._shaderValues.addDefine(MeshSprite3DShaderDeclaration.SHADERDEFINE_GPU_INSTANCE);
	                break;
	        }
	    }
	    _renderUpdateWithCamera(context, transform) {
	        var projectionView = context.projectionViewMatrix;
	        var element = context.renderElement;
	        switch (element.renderType) {
	            case RenderElement.RENDERTYPE_NORMAL:
	            case RenderElement.RENDERTYPE_STATICBATCH:
	            case RenderElement.RENDERTYPE_VERTEXBATCH:
	                if (transform) {
	                    Matrix4x4.multiply(projectionView, transform.worldMatrix, this._projectionViewWorldMatrix);
	                    this._shaderValues.setMatrix4x4(Sprite3D.MVPMATRIX, this._projectionViewWorldMatrix);
	                }
	                else {
	                    this._shaderValues.setMatrix4x4(Sprite3D.MVPMATRIX, projectionView);
	                }
	                break;
	            case RenderElement.RENDERTYPE_INSTANCEBATCH:
	                var mvpMatrixData = SubMeshInstanceBatch.instance.instanceMVPMatrixData;
	                var insBatches = element.instanceBatchElementList;
	                var elements = insBatches.elements;
	                var count = insBatches.length;
	                for (var i = 0; i < count; i++) {
	                    var worldMat = elements[i]._transform.worldMatrix;
	                    Utils3D.mulMatrixByArray(projectionView.elements, 0, worldMat.elements, 0, mvpMatrixData, i * 16);
	                }
	                SubMeshInstanceBatch.instance.instanceMVPMatrixBuffer.setData(mvpMatrixData.buffer, 0, 0, count * 16 * 4);
	                break;
	        }
	    }
	    _revertBatchRenderUpdate(context) {
	        var element = context.renderElement;
	        switch (element.renderType) {
	            case RenderElement.RENDERTYPE_STATICBATCH:
	                if (this._revertStaticBatchDefineUV1)
	                    this._shaderValues.removeDefine(MeshSprite3DShaderDeclaration.SHADERDEFINE_UV1);
	                if (this._revertStaticBatchDefineLightMapUV)
	                    this._shaderValues.addDefine(RenderableSprite3D.SHADERDEFINE_SCALEOFFSETLIGHTINGMAPUV);
	                break;
	            case RenderElement.RENDERTYPE_INSTANCEBATCH:
	                this._shaderValues.removeDefine(MeshSprite3DShaderDeclaration.SHADERDEFINE_GPU_INSTANCE);
	                break;
	        }
	    }
	    _destroy() {
	        (this._isPartOfStaticBatch) && (MeshRenderStaticBatchManager.instance._removeRenderSprite(this._owner));
	        super._destroy();
	    }
	}

	class MeshFilter {
	    constructor(owner) {
	        this._owner = owner;
	    }
	    get sharedMesh() {
	        return this._sharedMesh;
	    }
	    set sharedMesh(value) {
	        if (this._sharedMesh !== value) {
	            var defineDatas = this._owner._render._shaderValues;
	            var lastValue = this._sharedMesh;
	            if (lastValue) {
	                lastValue._removeReference();
	                this._getMeshDefine(lastValue, MeshFilter._meshVerticeDefine);
	                for (var i = 0, n = MeshFilter._meshVerticeDefine.length; i < n; i++)
	                    defineDatas.removeDefine(MeshFilter._meshVerticeDefine[i]);
	            }
	            if (value) {
	                value._addReference();
	                this._getMeshDefine(value, MeshFilter._meshVerticeDefine);
	                for (var i = 0, n = MeshFilter._meshVerticeDefine.length; i < n; i++)
	                    defineDatas.addDefine(MeshFilter._meshVerticeDefine[i]);
	            }
	            this._owner._render._onMeshChange(value);
	            this._sharedMesh = value;
	        }
	    }
	    _getMeshDefine(mesh, out) {
	        out.length = 0;
	        var define;
	        for (var i = 0, n = mesh._subMeshes.length; i < n; i++) {
	            var subMesh = mesh.getSubMesh(i);
	            var vertexElements = subMesh._vertexBuffer._vertexDeclaration._vertexElements;
	            for (var j = 0, m = vertexElements.length; j < m; j++) {
	                var vertexElement = vertexElements[j];
	                var name = vertexElement._elementUsage;
	                switch (name) {
	                    case VertexMesh.MESH_COLOR0:
	                        out.push(MeshSprite3DShaderDeclaration.SHADERDEFINE_COLOR);
	                        break;
	                    case VertexMesh.MESH_TEXTURECOORDINATE0:
	                        out.push(MeshSprite3DShaderDeclaration.SHADERDEFINE_UV0);
	                        break;
	                    case VertexMesh.MESH_TEXTURECOORDINATE1:
	                        out.push(MeshSprite3DShaderDeclaration.SHADERDEFINE_UV1);
	                        break;
	                }
	            }
	        }
	        return define;
	    }
	    destroy() {
	        this._owner = null;
	        (this._sharedMesh) && (this._sharedMesh._removeReference(), this._sharedMesh = null);
	    }
	}
	MeshFilter._meshVerticeDefine = [];

	class SubMeshDynamicBatch extends GeometryElement {
	    constructor() {
	        super();
	        this._bufferState = new BufferState();
	        var gl = Laya.LayaGL.instance;
	        var maxVerDec = VertexMesh.getVertexDeclaration("POSITION,NORMAL,COLOR,UV,UV1,TANGENT");
	        var maxByteCount = maxVerDec.vertexStride * SubMeshDynamicBatch.maxIndicesCount;
	        this._vertices = new Float32Array(maxByteCount / 4);
	        this._vertexBuffer = new VertexBuffer3D(maxByteCount, gl.DYNAMIC_DRAW);
	        this._indices = new Int16Array(SubMeshDynamicBatch.maxIndicesCount);
	        this._indexBuffer = new IndexBuffer3D(IndexBuffer3D.INDEXTYPE_USHORT, this._indices.length, gl.DYNAMIC_DRAW);
	        var memorySize = this._vertexBuffer._byteLength + this._indexBuffer._byteLength;
	        Laya.Resource._addMemory(memorySize, memorySize);
	    }
	    static __init__() {
	        SubMeshDynamicBatch.instance = new SubMeshDynamicBatch();
	    }
	    _getBatchVertices(vertexDeclaration, batchVertices, batchOffset, transform, element, subMesh) {
	        var vertexFloatCount = vertexDeclaration.vertexStride / 4;
	        var oriVertexes = subMesh._vertexBuffer.getFloat32Data();
	        var lightmapScaleOffset = element.render.lightmapScaleOffset;
	        var multiSubMesh = element._dynamicMultiSubMesh;
	        var vertexCount = element._dynamicVertexCount;
	        element._computeWorldPositionsAndNormals(this._positionOffset, this._normalOffset, multiSubMesh, vertexCount);
	        var worldPositions = element._dynamicWorldPositions;
	        var worldNormals = element._dynamicWorldNormals;
	        var indices = subMesh._indices;
	        for (var i = 0; i < vertexCount; i++) {
	            var index = multiSubMesh ? indices[i] : i;
	            var oriOffset = index * vertexFloatCount;
	            var bakeOffset = (i + batchOffset) * vertexFloatCount;
	            var oriOff = i * 3;
	            var bakOff = bakeOffset + this._positionOffset;
	            batchVertices[bakOff] = worldPositions[oriOff];
	            batchVertices[bakOff + 1] = worldPositions[oriOff + 1];
	            batchVertices[bakOff + 2] = worldPositions[oriOff + 2];
	            if (this._normalOffset !== -1) {
	                bakOff = bakeOffset + this._normalOffset;
	                batchVertices[bakOff] = worldNormals[oriOff];
	                batchVertices[bakOff + 1] = worldNormals[oriOff + 1];
	                batchVertices[bakOff + 2] = worldNormals[oriOff + 2];
	            }
	            if (this._colorOffset !== -1) {
	                bakOff = bakeOffset + this._colorOffset;
	                oriOff = oriOffset + this._colorOffset;
	                batchVertices[bakOff] = oriVertexes[oriOff];
	                batchVertices[bakOff + 1] = oriVertexes[oriOff + 1];
	                batchVertices[bakOff + 2] = oriVertexes[oriOff + 2];
	                batchVertices[bakOff + 3] = oriVertexes[oriOff + 3];
	            }
	            if (this._uv0Offset !== -1) {
	                bakOff = bakeOffset + this._uv0Offset;
	                oriOff = oriOffset + this._uv0Offset;
	                batchVertices[bakOff] = oriVertexes[oriOff];
	                batchVertices[bakOff + 1] = oriVertexes[oriOff + 1];
	            }
	            if (this._sTangentOffset !== -1) {
	                bakOff = bakeOffset + this._sTangentOffset;
	                oriOff = oriOffset + this._sTangentOffset;
	                batchVertices[bakOff] = oriVertexes[oriOff];
	                batchVertices[bakOff + 1] = oriVertexes[oriOff + 1];
	                batchVertices[bakOff + 2] = oriVertexes[oriOff + 2];
	                batchVertices[bakOff + 3] = oriVertexes[oriOff + 3];
	                bakOff = bakeOffset + this._sTangentOffset;
	                oriOff = oriOffset + this._sTangentOffset;
	                batchVertices[bakOff] = oriVertexes[oriOff];
	                batchVertices[bakOff + 1] = oriVertexes[oriOff + 1];
	                batchVertices[bakOff + 2] = oriVertexes[oriOff + 2];
	                batchVertices[bakOff + 3] = oriVertexes[oriOff + 3];
	            }
	        }
	    }
	    _getBatchIndices(batchIndices, batchIndexCount, batchVertexCount, transform, subMesh, multiSubMesh) {
	        var subIndices = subMesh._indices;
	        var k, m, batchOffset;
	        var isInvert = transform._isFrontFaceInvert;
	        if (multiSubMesh) {
	            if (isInvert) {
	                for (k = 0, m = subIndices.length; k < m; k += 3) {
	                    batchOffset = batchIndexCount + k;
	                    var index = batchVertexCount + k;
	                    batchIndices[batchOffset] = index;
	                    batchIndices[batchOffset + 1] = index + 2;
	                    batchIndices[batchOffset + 2] = index + 1;
	                }
	            }
	            else {
	                for (k = 0, m = subIndices.length; k < m; k += 3) {
	                    batchOffset = batchIndexCount + k;
	                    index = batchVertexCount + k;
	                    batchIndices[batchOffset] = index;
	                    batchIndices[batchOffset + 1] = index + 1;
	                    batchIndices[batchOffset + 2] = index + 2;
	                }
	            }
	        }
	        else {
	            if (isInvert) {
	                for (k = 0, m = subIndices.length; k < m; k += 3) {
	                    batchOffset = batchIndexCount + k;
	                    batchIndices[batchOffset] = batchVertexCount + subIndices[k];
	                    batchIndices[batchOffset + 1] = batchVertexCount + subIndices[k + 2];
	                    batchIndices[batchOffset + 2] = batchVertexCount + subIndices[k + 1];
	                }
	            }
	            else {
	                for (k = 0, m = subIndices.length; k < m; k += 3) {
	                    batchOffset = batchIndexCount + k;
	                    batchIndices[batchOffset] = batchVertexCount + subIndices[k];
	                    batchIndices[batchOffset + 1] = batchVertexCount + subIndices[k + 1];
	                    batchIndices[batchOffset + 2] = batchVertexCount + subIndices[k + 2];
	                }
	            }
	        }
	    }
	    _flush(vertexCount, indexCount) {
	        var gl = Laya.LayaGL.instance;
	        this._vertexBuffer.setData(this._vertices.buffer, 0, 0, vertexCount * (this._bufferState.vertexDeclaration.vertexStride));
	        this._indexBuffer.setData(this._indices, 0, 0, indexCount);
	        gl.drawElements(gl.TRIANGLES, indexCount, gl.UNSIGNED_SHORT, 0);
	    }
	    _prepareRender(state) {
	        var element = state.renderElement;
	        var vertexDeclaration = element.vertexBatchVertexDeclaration;
	        this._bufferState = ILaya3D.MeshRenderDynamicBatchManager.instance._getBufferState(vertexDeclaration);
	        this._positionOffset = vertexDeclaration.getVertexElementByUsage(VertexMesh.MESH_POSITION0)._offset / 4;
	        var normalElement = vertexDeclaration.getVertexElementByUsage(VertexMesh.MESH_NORMAL0);
	        this._normalOffset = normalElement ? normalElement._offset / 4 : -1;
	        var colorElement = vertexDeclaration.getVertexElementByUsage(VertexMesh.MESH_COLOR0);
	        this._colorOffset = colorElement ? colorElement._offset / 4 : -1;
	        var uv0Element = vertexDeclaration.getVertexElementByUsage(VertexMesh.MESH_TEXTURECOORDINATE0);
	        this._uv0Offset = uv0Element ? uv0Element._offset / 4 : -1;
	        var uv1Element = vertexDeclaration.getVertexElementByUsage(VertexMesh.MESH_TEXTURECOORDINATE1);
	        this._uv1Offset = uv1Element ? uv1Element._offset / 4 : -1;
	        var tangentElement = vertexDeclaration.getVertexElementByUsage(VertexMesh.MESH_TANGENT0);
	        this._sTangentOffset = tangentElement ? tangentElement._offset / 4 : -1;
	        return true;
	    }
	    _render(context) {
	        this._bufferState.bind();
	        var element = context.renderElement;
	        var vertexDeclaration = element.vertexBatchVertexDeclaration;
	        var batchElements = element.vertexBatchElementList;
	        var batchVertexCount = 0;
	        var batchIndexCount = 0;
	        var floatStride = vertexDeclaration.vertexStride / 4;
	        var renderBatchCount = 0;
	        var elementCount = batchElements.length;
	        var elements = batchElements.elements;
	        for (var i = 0; i < elementCount; i++) {
	            var subElement = elements[i];
	            var subMesh = subElement._geometry;
	            var indexCount = subMesh._indexCount;
	            if (batchIndexCount + indexCount > SubMeshDynamicBatch.maxIndicesCount) {
	                this._flush(batchVertexCount, batchIndexCount);
	                renderBatchCount++;
	                Laya.Stat.trianglesFaces += batchIndexCount / 3;
	                batchVertexCount = batchIndexCount = 0;
	            }
	            var transform = subElement._transform;
	            this._getBatchVertices(vertexDeclaration, this._vertices, batchVertexCount, transform, subElement, subMesh);
	            this._getBatchIndices(this._indices, batchIndexCount, batchVertexCount, transform, subMesh, subElement._dynamicMultiSubMesh);
	            batchVertexCount += subElement._dynamicVertexCount;
	            batchIndexCount += indexCount;
	        }
	        this._flush(batchVertexCount, batchIndexCount);
	        renderBatchCount++;
	        Laya.Stat.renderBatches += renderBatchCount;
	        Laya.Stat.savedRenderBatches += elementCount - renderBatchCount;
	        Laya.Stat.trianglesFaces += batchIndexCount / 3;
	    }
	}
	SubMeshDynamicBatch.maxAllowVertexCount = 10;
	SubMeshDynamicBatch.maxAllowAttribueCount = 900;
	SubMeshDynamicBatch.maxIndicesCount = 32000;

	class MeshRenderDynamicBatchManager extends DynamicBatchManager {
	    constructor() {
	        super();
	        this._instanceBatchOpaqueMarks = [];
	        this._vertexBatchOpaqueMarks = [];
	        this._cacheBufferStates = [];
	        this._updateCountMark = 0;
	    }
	    getInstanceBatchOpaquaMark(receiveShadow, materialID, subMeshID, invertFace) {
	        var instanceReceiveShadowMarks = (this._instanceBatchOpaqueMarks[receiveShadow ? 0 : 1]) || (this._instanceBatchOpaqueMarks[receiveShadow ? 0 : 1] = []);
	        var instanceMaterialMarks = (instanceReceiveShadowMarks[materialID]) || (instanceReceiveShadowMarks[materialID] = []);
	        var instancSubMeshMarks = (instanceMaterialMarks[subMeshID]) || (instanceMaterialMarks[subMeshID] = []);
	        return instancSubMeshMarks[invertFace ? 1 : 0] || (instancSubMeshMarks[invertFace ? 1 : 0] = new BatchMark());
	    }
	    getVertexBatchOpaquaMark(lightMapIndex, receiveShadow, materialID, verDecID) {
	        var dynLightMapMarks = (this._vertexBatchOpaqueMarks[lightMapIndex]) || (this._vertexBatchOpaqueMarks[lightMapIndex] = []);
	        var dynReceiveShadowMarks = (dynLightMapMarks[receiveShadow ? 0 : 1]) || (dynLightMapMarks[receiveShadow ? 0 : 1] = []);
	        var dynMaterialMarks = (dynReceiveShadowMarks[materialID]) || (dynReceiveShadowMarks[materialID] = []);
	        return dynMaterialMarks[verDecID] || (dynMaterialMarks[verDecID] = new BatchMark());
	    }
	    _getBufferState(vertexDeclaration) {
	        var bufferState = this._cacheBufferStates[vertexDeclaration.id];
	        if (!bufferState) {
	            var instance = SubMeshDynamicBatch.instance;
	            bufferState = new BufferState();
	            bufferState.bind();
	            var vertexBuffer = instance._vertexBuffer;
	            vertexBuffer.vertexDeclaration = vertexDeclaration;
	            bufferState.applyVertexBuffer(vertexBuffer);
	            bufferState.applyIndexBuffer(instance._indexBuffer);
	            bufferState.unBind();
	            this._cacheBufferStates[vertexDeclaration.id] = bufferState;
	        }
	        return bufferState;
	    }
	    _getBatchRenderElementFromPool() {
	        var renderElement = this._batchRenderElementPool[this._batchRenderElementPoolIndex++];
	        if (!renderElement) {
	            renderElement = new SubMeshRenderElement();
	            this._batchRenderElementPool[this._batchRenderElementPoolIndex - 1] = renderElement;
	            renderElement.vertexBatchElementList = new SingletonList();
	            renderElement.instanceBatchElementList = new SingletonList();
	        }
	        return renderElement;
	    }
	    _clear() {
	        super._clear();
	        this._updateCountMark++;
	    }
	}
	MeshRenderDynamicBatchManager.instance = new MeshRenderDynamicBatchManager();

	class MeshSprite3D extends RenderableSprite3D {
	    static __init__() {
	        MeshSprite3DShaderDeclaration.SHADERDEFINE_UV0 = Shader3D.getDefineByName("UV");
	        MeshSprite3DShaderDeclaration.SHADERDEFINE_COLOR = Shader3D.getDefineByName("COLOR");
	        MeshSprite3DShaderDeclaration.SHADERDEFINE_UV1 = Shader3D.getDefineByName("UV1");
	        MeshSprite3DShaderDeclaration.SHADERDEFINE_GPU_INSTANCE = Shader3D.getDefineByName("GPU_INSTANCE");
	        StaticBatchManager._registerManager(MeshRenderStaticBatchManager.instance);
	        DynamicBatchManager._registerManager(MeshRenderDynamicBatchManager.instance);
	    }
	    get meshFilter() {
	        return this._meshFilter;
	    }
	    get meshRenderer() {
	        return this._render;
	    }
	    constructor(mesh = null, name = null) {
	        super(name);
	        this._meshFilter = new MeshFilter(this);
	        this._render = new MeshRenderer(this);
	        (mesh) && (this._meshFilter.sharedMesh = mesh);
	    }
	    _parse(data, spriteMap) {
	        super._parse(data, spriteMap);
	        var render = this.meshRenderer;
	        var lightmapIndex = data.lightmapIndex;
	        (lightmapIndex != null) && (render.lightmapIndex = lightmapIndex);
	        var lightmapScaleOffsetArray = data.lightmapScaleOffset;
	        (lightmapScaleOffsetArray) && (render.lightmapScaleOffset = new Vector4(lightmapScaleOffsetArray[0], lightmapScaleOffsetArray[1], lightmapScaleOffsetArray[2], lightmapScaleOffsetArray[3]));
	        (data.meshPath != undefined) && (this.meshFilter.sharedMesh = Laya.Loader.getRes(data.meshPath));
	        (data.enableRender != undefined) && (this.meshRenderer.enable = data.enableRender);
	        var materials = data.materials;
	        if (materials) {
	            var sharedMaterials = render.sharedMaterials;
	            var materialCount = materials.length;
	            sharedMaterials.length = materialCount;
	            for (var i = 0; i < materialCount; i++) {
	                sharedMaterials[i] = Laya.Loader.getRes(materials[i].path);
	            }
	            render.sharedMaterials = sharedMaterials;
	        }
	    }
	    _addToInitStaticBatchManager() {
	        if (this.meshFilter.sharedMesh)
	            MeshRenderStaticBatchManager.instance._addBatchSprite(this);
	    }
	    _cloneTo(destObject, rootSprite, dstSprite) {
	        var meshSprite3D = destObject;
	        meshSprite3D._meshFilter.sharedMesh = this._meshFilter.sharedMesh;
	        var meshRender = this._render;
	        var destMeshRender = meshSprite3D._render;
	        destMeshRender.enable = meshRender.enable;
	        destMeshRender.sharedMaterials = meshRender.sharedMaterials;
	        destMeshRender.castShadow = meshRender.castShadow;
	        var lightmapScaleOffset = meshRender.lightmapScaleOffset;
	        lightmapScaleOffset && (destMeshRender.lightmapScaleOffset = lightmapScaleOffset.clone());
	        destMeshRender.lightmapIndex = meshRender.lightmapIndex;
	        destMeshRender.receiveShadow = meshRender.receiveShadow;
	        destMeshRender.sortingFudge = meshRender.sortingFudge;
	        super._cloneTo(destObject, rootSprite, dstSprite);
	    }
	    destroy(destroyChild = true) {
	        if (this.destroyed)
	            return;
	        super.destroy(destroyChild);
	        this._meshFilter.destroy();
	    }
	    _create() {
	        return new MeshSprite3D();
	    }
	}

	class GradientMode {
	}
	GradientMode.Blend = 0;
	GradientMode.Fixed = 1;

	class Gradient {
	    constructor(maxColorRGBKeyCount, maxColorAlphaKeyCount) {
	        this._mode = 0;
	        this._maxColorRGBKeysCount = 0;
	        this._maxColorAlphaKeysCount = 0;
	        this._colorRGBKeysCount = 0;
	        this._colorAlphaKeysCount = 0;
	        this._alphaElements = null;
	        this._rgbElements = null;
	        this._maxColorRGBKeysCount = maxColorRGBKeyCount;
	        this._maxColorAlphaKeysCount = maxColorAlphaKeyCount;
	        this._rgbElements = new Float32Array(maxColorRGBKeyCount * 4);
	        this._alphaElements = new Float32Array(maxColorAlphaKeyCount * 2);
	    }
	    get mode() {
	        return this._mode;
	    }
	    set mode(value) {
	        this._mode = value;
	    }
	    get colorRGBKeysCount() {
	        return this._colorRGBKeysCount;
	    }
	    get colorAlphaKeysCount() {
	        return this._colorAlphaKeysCount;
	    }
	    get maxColorRGBKeysCount() {
	        return this._maxColorRGBKeysCount;
	    }
	    get maxColorAlphaKeysCount() {
	        return this._maxColorAlphaKeysCount;
	    }
	    addColorRGB(key, value) {
	        if (this._colorRGBKeysCount < this._maxColorRGBKeysCount) {
	            var offset = this._colorRGBKeysCount * 4;
	            this._rgbElements[offset] = key;
	            this._rgbElements[offset + 1] = value.r;
	            this._rgbElements[offset + 2] = value.g;
	            this._rgbElements[offset + 3] = value.b;
	            this._colorRGBKeysCount++;
	        }
	        else {
	            console.warn("Gradient:warning:data count must lessEqual than " + this._maxColorRGBKeysCount);
	        }
	    }
	    addColorAlpha(key, value) {
	        if (this._colorAlphaKeysCount < this._maxColorAlphaKeysCount) {
	            var offset = this._colorAlphaKeysCount * 2;
	            this._alphaElements[offset] = key;
	            this._alphaElements[offset + 1] = value;
	            this._colorAlphaKeysCount++;
	        }
	        else {
	            console.warn("Gradient:warning:data count must lessEqual than " + this._maxColorAlphaKeysCount);
	        }
	    }
	    updateColorRGB(index, key, value) {
	        if (index < this._colorRGBKeysCount) {
	            var offset = index * 4;
	            this._rgbElements[offset] = key;
	            this._rgbElements[offset + 1] = value.r;
	            this._rgbElements[offset + 2] = value.g;
	            this._rgbElements[offset + 3] = value.b;
	        }
	        else {
	            console.warn("Gradient:warning:index must lessEqual than colorRGBKeysCount:" + this._colorRGBKeysCount);
	        }
	    }
	    updateColorAlpha(index, key, value) {
	        if (index < this._colorAlphaKeysCount) {
	            var offset = index * 2;
	            this._alphaElements[offset] = key;
	            this._alphaElements[offset + 1] = value;
	        }
	        else {
	            console.warn("Gradient:warning:index must lessEqual than colorAlphaKeysCount:" + this._colorAlphaKeysCount);
	        }
	    }
	    evaluateColorRGB(lerpFactor, out, startSearchIndex = 0, reverseSearch = false) {
	        lerpFactor = Math.min(Math.max(lerpFactor, 0.0), 1.0);
	        var rgbElements = this._rgbElements;
	        var curIndex = startSearchIndex;
	        if (reverseSearch) {
	            for (var i = curIndex; i >= 0; i--) {
	                var offset = i * 4;
	                var left = rgbElements[offset];
	                if (lerpFactor === left) {
	                    out.r = rgbElements[offset + 1];
	                    out.g = rgbElements[offset + 2];
	                    out.b = rgbElements[offset + 3];
	                    return curIndex;
	                }
	                switch (this._mode) {
	                    case GradientMode.Blend:
	                        if (lerpFactor > left) {
	                            var right = rgbElements[offset + 4];
	                            if (lerpFactor > right)
	                                throw "Gradient:wrong startSearchIndex.";
	                            var diff = right - left;
	                            var y1 = right - lerpFactor;
	                            var y2 = lerpFactor - left;
	                            out.r = (y1 * rgbElements[offset + 1] + y2 * rgbElements[offset + 5]) / diff;
	                            out.g = (y1 * rgbElements[offset + 2] + y2 * rgbElements[offset + 6]) / diff;
	                            out.b = (y1 * rgbElements[offset + 3] + y2 * rgbElements[offset + 7]) / diff;
	                            return curIndex;
	                        }
	                        else {
	                            curIndex--;
	                            continue;
	                        }
	                    case GradientMode.Fixed:
	                        if (lerpFactor > left) {
	                            if (lerpFactor > rgbElements[offset + 4])
	                                throw "Gradient:wrong startSearchIndex.";
	                            out.r = rgbElements[offset + 5];
	                            out.g = rgbElements[offset + 6];
	                            out.b = rgbElements[offset + 7];
	                            return curIndex;
	                        }
	                        else {
	                            curIndex--;
	                            continue;
	                        }
	                    default:
	                        throw "Gradient:unknown mode.";
	                }
	            }
	        }
	        else {
	            for (var i = 0, n = this._rgbElements.length; i < n; i++) {
	                offset = i * 4;
	                var right = rgbElements[offset];
	                if (lerpFactor === right) {
	                    out.r = rgbElements[offset + 1];
	                    out.g = rgbElements[offset + 2];
	                    out.b = rgbElements[offset + 3];
	                    return curIndex;
	                }
	                switch (this._mode) {
	                    case GradientMode.Blend:
	                        if (lerpFactor < right) {
	                            var left = rgbElements[offset - 4];
	                            if (lerpFactor < left)
	                                throw "Gradient:wrong startSearchIndex.";
	                            var diff = right - left;
	                            var y1 = right - lerpFactor;
	                            var y2 = lerpFactor - left;
	                            out.r = (y1 * rgbElements[offset - 3] + y2 * rgbElements[offset + 1]) / diff;
	                            out.g = (y1 * rgbElements[offset - 2] + y2 * rgbElements[offset + 2]) / diff;
	                            out.b = (y1 * rgbElements[offset - 1] + y2 * rgbElements[offset + 3]) / diff;
	                            return curIndex;
	                        }
	                        else {
	                            curIndex++;
	                            continue;
	                        }
	                    case GradientMode.Fixed:
	                        if (lerpFactor < right) {
	                            if (lerpFactor < rgbElements[offset - 4])
	                                throw "Gradient:wrong startSearchIndex.";
	                            out.r = rgbElements[offset + 1];
	                            out.g = rgbElements[offset + 2];
	                            out.b = rgbElements[offset + 3];
	                            return curIndex;
	                        }
	                        else {
	                            curIndex++;
	                            continue;
	                        }
	                    default:
	                        throw "Gradient:unknown mode.";
	                }
	            }
	        }
	        return curIndex;
	    }
	    evaluateColorAlpha(lerpFactor, outColor, startSearchIndex = 0, reverseSearch = false) {
	        lerpFactor = Math.min(Math.max(lerpFactor, 0.0), 1.0);
	        var alphaElements = this._alphaElements;
	        var curIndex = startSearchIndex;
	        if (reverseSearch) {
	            for (var i = curIndex; i >= 0; i--) {
	                var offset = i * 2;
	                var left = alphaElements[offset];
	                if (lerpFactor === left) {
	                    outColor.a = alphaElements[offset + 1];
	                    return curIndex;
	                }
	                switch (this._mode) {
	                    case GradientMode.Blend:
	                        if (lerpFactor > left) {
	                            var right = alphaElements[offset + 2];
	                            if (lerpFactor > right)
	                                throw "Gradient:wrong startSearchIndex.";
	                            var diff = right - left;
	                            var x1 = right - lerpFactor;
	                            var x2 = lerpFactor - left;
	                            outColor.a = (x1 * alphaElements[offset + 1] + x2 * alphaElements[offset + 3]) / diff;
	                            return curIndex;
	                        }
	                        else {
	                            curIndex--;
	                            continue;
	                        }
	                    case GradientMode.Fixed:
	                        if (lerpFactor > left) {
	                            if (lerpFactor > alphaElements[offset + 2])
	                                throw "Gradient:wrong startSearchIndex.";
	                            outColor.a = alphaElements[offset + 3];
	                            return curIndex;
	                        }
	                        else {
	                            curIndex--;
	                            continue;
	                        }
	                    default:
	                        throw "Gradient:unknown mode.";
	                }
	            }
	        }
	        else {
	            for (var i = curIndex, n = this._alphaElements.length; i < n; i++) {
	                var offset = i * 2;
	                var right = alphaElements[offset];
	                if (lerpFactor === right) {
	                    outColor.a = alphaElements[offset + 1];
	                    return curIndex;
	                }
	                switch (this._mode) {
	                    case GradientMode.Blend:
	                        if (lerpFactor < right) {
	                            var left = alphaElements[offset - 2];
	                            if (lerpFactor < left)
	                                throw "Gradient:wrong startSearchIndex.";
	                            var diff = right - left;
	                            var x1 = right - lerpFactor;
	                            var x2 = lerpFactor - left;
	                            outColor.a = (x1 * alphaElements[offset - 1] + x2 * alphaElements[offset + 1]) / diff;
	                            return curIndex;
	                        }
	                        else {
	                            curIndex++;
	                            continue;
	                        }
	                    case GradientMode.Fixed:
	                        if (lerpFactor < right) {
	                            if (lerpFactor < alphaElements[offset - 2])
	                                throw "Gradient:wrong startSearchIndex.";
	                            outColor.a = alphaElements[offset + 1];
	                            return curIndex;
	                        }
	                        else {
	                            curIndex++;
	                            continue;
	                        }
	                    default:
	                        throw "Gradient:unknown mode.";
	                }
	            }
	        }
	        return curIndex;
	    }
	    cloneTo(destObject) {
	        var destGradientDataColor = destObject;
	        var i, n;
	        destGradientDataColor._colorAlphaKeysCount = this._colorAlphaKeysCount;
	        var destAlphaElements = destGradientDataColor._alphaElements;
	        for (i = 0, n = this._alphaElements.length; i < n; i++)
	            destAlphaElements[i] = this._alphaElements[i];
	        destGradientDataColor._colorRGBKeysCount = this._colorRGBKeysCount;
	        var destRGBElements = destGradientDataColor._rgbElements;
	        for (i = 0, n = this._rgbElements.length; i < n; i++)
	            destRGBElements[i] = this._rgbElements[i];
	    }
	    clone() {
	        var destGradientDataColor = new Gradient(this._maxColorRGBKeysCount, this._maxColorAlphaKeysCount);
	        this.cloneTo(destGradientDataColor);
	        return destGradientDataColor;
	    }
	}

	class ShurikenParticleMaterial extends BaseMaterial {
	    constructor() {
	        super();
	        this.setShaderName("PARTICLESHURIKEN");
	        this._color = new Vector4(1.0, 1.0, 1.0, 1.0);
	        this.renderMode = ShurikenParticleMaterial.RENDERMODE_ALPHABLENDED;
	    }
	    static __initDefine__() {
	        ShurikenParticleMaterial.SHADERDEFINE_DIFFUSEMAP = Shader3D.getDefineByName("DIFFUSEMAP");
	        ShurikenParticleMaterial.SHADERDEFINE_TINTCOLOR = Shader3D.getDefineByName("TINTCOLOR");
	        ShurikenParticleMaterial.SHADERDEFINE_ADDTIVEFOG = Shader3D.getDefineByName("ADDTIVEFOG");
	        ShurikenParticleMaterial.SHADERDEFINE_TILINGOFFSET = Shader3D.getDefineByName("TILINGOFFSET");
	    }
	    get _TintColorR() {
	        return this._color.x;
	    }
	    set _TintColorR(value) {
	        this._color.x = value;
	        this.color = this._color;
	    }
	    get _TintColorG() {
	        return this._color.y;
	    }
	    set _TintColorG(value) {
	        this._color.y = value;
	        this.color = this._color;
	    }
	    get _TintColorB() {
	        return this._color.z;
	    }
	    set _TintColorB(value) {
	        this._color.z = value;
	        this.color = this._color;
	    }
	    get _TintColorA() {
	        return this._color.w;
	    }
	    set _TintColorA(value) {
	        this._color.w = value;
	        this.color = this._color;
	    }
	    get _MainTex_STX() {
	        return this._shaderValues.getVector(ShurikenParticleMaterial.TILINGOFFSET).x;
	    }
	    set _MainTex_STX(x) {
	        var tilOff = this._shaderValues.getVector(ShurikenParticleMaterial.TILINGOFFSET);
	        tilOff.x = x;
	        this.tilingOffset = tilOff;
	    }
	    get _MainTex_STY() {
	        return this._shaderValues.getVector(ShurikenParticleMaterial.TILINGOFFSET).y;
	    }
	    set _MainTex_STY(y) {
	        var tilOff = this._shaderValues.getVector(ShurikenParticleMaterial.TILINGOFFSET);
	        tilOff.y = y;
	        this.tilingOffset = tilOff;
	    }
	    get _MainTex_STZ() {
	        return this._shaderValues.getVector(ShurikenParticleMaterial.TILINGOFFSET).z;
	    }
	    set _MainTex_STZ(z) {
	        var tilOff = this._shaderValues.getVector(ShurikenParticleMaterial.TILINGOFFSET);
	        tilOff.z = z;
	        this.tilingOffset = tilOff;
	    }
	    get _MainTex_STW() {
	        return this._shaderValues.getVector(ShurikenParticleMaterial.TILINGOFFSET).w;
	    }
	    set _MainTex_STW(w) {
	        var tilOff = this._shaderValues.getVector(ShurikenParticleMaterial.TILINGOFFSET);
	        tilOff.w = w;
	        this.tilingOffset = tilOff;
	    }
	    set renderMode(value) {
	        switch (value) {
	            case ShurikenParticleMaterial.RENDERMODE_ADDTIVE:
	                this.renderQueue = BaseMaterial.RENDERQUEUE_TRANSPARENT;
	                this.depthWrite = false;
	                this.cull = RenderState.CULL_NONE;
	                this.blend = RenderState.BLEND_ENABLE_ALL;
	                this.blendSrc = RenderState.BLENDPARAM_SRC_ALPHA;
	                this.blendDst = RenderState.BLENDPARAM_ONE;
	                this.alphaTest = false;
	                this._shaderValues.addDefine(ShurikenParticleMaterial.SHADERDEFINE_ADDTIVEFOG);
	                break;
	            case ShurikenParticleMaterial.RENDERMODE_ALPHABLENDED:
	                this.renderQueue = BaseMaterial.RENDERQUEUE_TRANSPARENT;
	                this.depthWrite = false;
	                this.cull = RenderState.CULL_NONE;
	                this.blend = RenderState.BLEND_ENABLE_ALL;
	                this.blendSrc = RenderState.BLENDPARAM_SRC_ALPHA;
	                this.blendDst = RenderState.BLENDPARAM_ONE_MINUS_SRC_ALPHA;
	                this.alphaTest = false;
	                this._shaderValues.removeDefine(ShurikenParticleMaterial.SHADERDEFINE_ADDTIVEFOG);
	                break;
	            default:
	                throw new Error("ShurikenParticleMaterial : renderMode value error.");
	        }
	    }
	    get colorR() {
	        return this._TintColorR;
	    }
	    set colorR(value) {
	        this._TintColorR = value;
	    }
	    get colorG() {
	        return this._TintColorG;
	    }
	    set colorG(value) {
	        this._TintColorG = value;
	    }
	    get colorB() {
	        return this._TintColorB;
	    }
	    set colorB(value) {
	        this._TintColorB = value;
	    }
	    get colorA() {
	        return this._TintColorA;
	    }
	    set colorA(value) {
	        this._TintColorA = value;
	    }
	    get color() {
	        return this._shaderValues.getVector(ShurikenParticleMaterial.TINTCOLOR);
	    }
	    set color(value) {
	        if (value)
	            this._shaderValues.addDefine(ShurikenParticleMaterial.SHADERDEFINE_TINTCOLOR);
	        else
	            this._shaderValues.removeDefine(ShurikenParticleMaterial.SHADERDEFINE_TINTCOLOR);
	        this._shaderValues.setVector(ShurikenParticleMaterial.TINTCOLOR, value);
	    }
	    get tilingOffsetX() {
	        return this._MainTex_STX;
	    }
	    set tilingOffsetX(x) {
	        this._MainTex_STX = x;
	    }
	    get tilingOffsetY() {
	        return this._MainTex_STY;
	    }
	    set tilingOffsetY(y) {
	        this._MainTex_STY = y;
	    }
	    get tilingOffsetZ() {
	        return this._MainTex_STZ;
	    }
	    set tilingOffsetZ(z) {
	        this._MainTex_STZ = z;
	    }
	    get tilingOffsetW() {
	        return this._MainTex_STW;
	    }
	    set tilingOffsetW(w) {
	        this._MainTex_STW = w;
	    }
	    get tilingOffset() {
	        return this._shaderValues.getVector(ShurikenParticleMaterial.TILINGOFFSET);
	    }
	    set tilingOffset(value) {
	        if (value) {
	            if (value.x != 1 || value.y != 1 || value.z != 0 || value.w != 0)
	                this._shaderValues.addDefine(ShurikenParticleMaterial.SHADERDEFINE_TILINGOFFSET);
	            else
	                this._shaderValues.removeDefine(ShurikenParticleMaterial.SHADERDEFINE_TILINGOFFSET);
	        }
	        else {
	            this._shaderValues.removeDefine(ShurikenParticleMaterial.SHADERDEFINE_TILINGOFFSET);
	        }
	        this._shaderValues.setVector(ShurikenParticleMaterial.TILINGOFFSET, value);
	    }
	    get texture() {
	        return this._shaderValues.getTexture(ShurikenParticleMaterial.DIFFUSETEXTURE);
	    }
	    set texture(value) {
	        if (value)
	            this._shaderValues.addDefine(ShurikenParticleMaterial.SHADERDEFINE_DIFFUSEMAP);
	        else
	            this._shaderValues.removeDefine(ShurikenParticleMaterial.SHADERDEFINE_DIFFUSEMAP);
	        this._shaderValues.setTexture(ShurikenParticleMaterial.DIFFUSETEXTURE, value);
	    }
	    get depthWrite() {
	        return this._shaderValues.getBool(ShurikenParticleMaterial.DEPTH_WRITE);
	    }
	    set depthWrite(value) {
	        this._shaderValues.setBool(ShurikenParticleMaterial.DEPTH_WRITE, value);
	    }
	    get cull() {
	        return this._shaderValues.getInt(ShurikenParticleMaterial.CULL);
	    }
	    set cull(value) {
	        this._shaderValues.setInt(ShurikenParticleMaterial.CULL, value);
	    }
	    get blend() {
	        return this._shaderValues.getInt(ShurikenParticleMaterial.BLEND);
	    }
	    set blend(value) {
	        this._shaderValues.setInt(ShurikenParticleMaterial.BLEND, value);
	    }
	    get blendSrc() {
	        return this._shaderValues.getInt(ShurikenParticleMaterial.BLEND_SRC);
	    }
	    set blendSrc(value) {
	        this._shaderValues.setInt(ShurikenParticleMaterial.BLEND_SRC, value);
	    }
	    get blendDst() {
	        return this._shaderValues.getInt(ShurikenParticleMaterial.BLEND_DST);
	    }
	    set blendDst(value) {
	        this._shaderValues.setInt(ShurikenParticleMaterial.BLEND_DST, value);
	    }
	    get depthTest() {
	        return this._shaderValues.getInt(ShurikenParticleMaterial.DEPTH_TEST);
	    }
	    set depthTest(value) {
	        this._shaderValues.setInt(ShurikenParticleMaterial.DEPTH_TEST, value);
	    }
	    clone() {
	        var dest = new ShurikenParticleMaterial();
	        this.cloneTo(dest);
	        return dest;
	    }
	}
	ShurikenParticleMaterial.RENDERMODE_ALPHABLENDED = 0;
	ShurikenParticleMaterial.RENDERMODE_ADDTIVE = 1;
	ShurikenParticleMaterial.DIFFUSETEXTURE = Shader3D.propertyNameToID("u_texture");
	ShurikenParticleMaterial.TINTCOLOR = Shader3D.propertyNameToID("u_Tintcolor");
	ShurikenParticleMaterial.TILINGOFFSET = Shader3D.propertyNameToID("u_TilingOffset");
	ShurikenParticleMaterial.CULL = Shader3D.propertyNameToID("s_Cull");
	ShurikenParticleMaterial.BLEND = Shader3D.propertyNameToID("s_Blend");
	ShurikenParticleMaterial.BLEND_SRC = Shader3D.propertyNameToID("s_BlendSrc");
	ShurikenParticleMaterial.BLEND_DST = Shader3D.propertyNameToID("s_BlendDst");
	ShurikenParticleMaterial.DEPTH_TEST = Shader3D.propertyNameToID("s_DepthTest");
	ShurikenParticleMaterial.DEPTH_WRITE = Shader3D.propertyNameToID("s_DepthWrite");

	class Physics3DUtils {
	    constructor() {
	    }
	    static setColliderCollision(collider1, collider2, collsion) {
	    }
	    static getIColliderCollision(collider1, collider2) {
	        return false;
	    }
	}
	Physics3DUtils.COLLISIONFILTERGROUP_DEFAULTFILTER = 0x1;
	Physics3DUtils.COLLISIONFILTERGROUP_STATICFILTER = 0x2;
	Physics3DUtils.COLLISIONFILTERGROUP_KINEMATICFILTER = 0x4;
	Physics3DUtils.COLLISIONFILTERGROUP_DEBRISFILTER = 0x8;
	Physics3DUtils.COLLISIONFILTERGROUP_SENSORTRIGGER = 0x10;
	Physics3DUtils.COLLISIONFILTERGROUP_CHARACTERFILTER = 0x20;
	Physics3DUtils.COLLISIONFILTERGROUP_CUSTOMFILTER1 = 0x40;
	Physics3DUtils.COLLISIONFILTERGROUP_CUSTOMFILTER2 = 0x80;
	Physics3DUtils.COLLISIONFILTERGROUP_CUSTOMFILTER3 = 0x100;
	Physics3DUtils.COLLISIONFILTERGROUP_CUSTOMFILTER4 = 0x200;
	Physics3DUtils.COLLISIONFILTERGROUP_CUSTOMFILTER5 = 0x400;
	Physics3DUtils.COLLISIONFILTERGROUP_CUSTOMFILTER6 = 0x800;
	Physics3DUtils.COLLISIONFILTERGROUP_CUSTOMFILTER7 = 0x1000;
	Physics3DUtils.COLLISIONFILTERGROUP_CUSTOMFILTER8 = 0x2000;
	Physics3DUtils.COLLISIONFILTERGROUP_CUSTOMFILTER9 = 0x4000;
	Physics3DUtils.COLLISIONFILTERGROUP_CUSTOMFILTER10 = 0x8000;
	Physics3DUtils.COLLISIONFILTERGROUP_ALLFILTER = -1;
	Physics3DUtils.gravity = new Vector3(0, -9.81, 0);

	class ShuriKenParticle3DShaderDeclaration {
	}
	ShuriKenParticle3DShaderDeclaration.WORLDPOSITION = Shader3D.propertyNameToID("u_WorldPosition");
	ShuriKenParticle3DShaderDeclaration.WORLDROTATION = Shader3D.propertyNameToID("u_WorldRotation");
	ShuriKenParticle3DShaderDeclaration.POSITIONSCALE = Shader3D.propertyNameToID("u_PositionScale");
	ShuriKenParticle3DShaderDeclaration.SIZESCALE = Shader3D.propertyNameToID("u_SizeScale");
	ShuriKenParticle3DShaderDeclaration.SCALINGMODE = Shader3D.propertyNameToID("u_ScalingMode");
	ShuriKenParticle3DShaderDeclaration.GRAVITY = Shader3D.propertyNameToID("u_Gravity");
	ShuriKenParticle3DShaderDeclaration.THREEDSTARTROTATION = Shader3D.propertyNameToID("u_ThreeDStartRotation");
	ShuriKenParticle3DShaderDeclaration.STRETCHEDBILLBOARDLENGTHSCALE = Shader3D.propertyNameToID("u_StretchedBillboardLengthScale");
	ShuriKenParticle3DShaderDeclaration.STRETCHEDBILLBOARDSPEEDSCALE = Shader3D.propertyNameToID("u_StretchedBillboardSpeedScale");
	ShuriKenParticle3DShaderDeclaration.SIMULATIONSPACE = Shader3D.propertyNameToID("u_SimulationSpace");
	ShuriKenParticle3DShaderDeclaration.CURRENTTIME = Shader3D.propertyNameToID("u_CurrentTime");
	ShuriKenParticle3DShaderDeclaration.VOLVELOCITYCONST = Shader3D.propertyNameToID("u_VOLVelocityConst");
	ShuriKenParticle3DShaderDeclaration.VOLVELOCITYGRADIENTX = Shader3D.propertyNameToID("u_VOLVelocityGradientX");
	ShuriKenParticle3DShaderDeclaration.VOLVELOCITYGRADIENTY = Shader3D.propertyNameToID("u_VOLVelocityGradientY");
	ShuriKenParticle3DShaderDeclaration.VOLVELOCITYGRADIENTZ = Shader3D.propertyNameToID("u_VOLVelocityGradientZ");
	ShuriKenParticle3DShaderDeclaration.VOLVELOCITYCONSTMAX = Shader3D.propertyNameToID("u_VOLVelocityConstMax");
	ShuriKenParticle3DShaderDeclaration.VOLVELOCITYGRADIENTXMAX = Shader3D.propertyNameToID("u_VOLVelocityGradientMaxX");
	ShuriKenParticle3DShaderDeclaration.VOLVELOCITYGRADIENTYMAX = Shader3D.propertyNameToID("u_VOLVelocityGradientMaxY");
	ShuriKenParticle3DShaderDeclaration.VOLVELOCITYGRADIENTZMAX = Shader3D.propertyNameToID("u_VOLVelocityGradientMaxZ");
	ShuriKenParticle3DShaderDeclaration.VOLSPACETYPE = Shader3D.propertyNameToID("u_VOLSpaceType");
	ShuriKenParticle3DShaderDeclaration.COLOROVERLIFEGRADIENTALPHAS = Shader3D.propertyNameToID("u_ColorOverLifeGradientAlphas");
	ShuriKenParticle3DShaderDeclaration.COLOROVERLIFEGRADIENTCOLORS = Shader3D.propertyNameToID("u_ColorOverLifeGradientColors");
	ShuriKenParticle3DShaderDeclaration.MAXCOLOROVERLIFEGRADIENTALPHAS = Shader3D.propertyNameToID("u_MaxColorOverLifeGradientAlphas");
	ShuriKenParticle3DShaderDeclaration.MAXCOLOROVERLIFEGRADIENTCOLORS = Shader3D.propertyNameToID("u_MaxColorOverLifeGradientColors");
	ShuriKenParticle3DShaderDeclaration.SOLSIZEGRADIENT = Shader3D.propertyNameToID("u_SOLSizeGradient");
	ShuriKenParticle3DShaderDeclaration.SOLSIZEGRADIENTX = Shader3D.propertyNameToID("u_SOLSizeGradientX");
	ShuriKenParticle3DShaderDeclaration.SOLSIZEGRADIENTY = Shader3D.propertyNameToID("u_SOLSizeGradientY");
	ShuriKenParticle3DShaderDeclaration.SOLSizeGradientZ = Shader3D.propertyNameToID("u_SOLSizeGradientZ");
	ShuriKenParticle3DShaderDeclaration.SOLSizeGradientMax = Shader3D.propertyNameToID("u_SOLSizeGradientMax");
	ShuriKenParticle3DShaderDeclaration.SOLSIZEGRADIENTXMAX = Shader3D.propertyNameToID("u_SOLSizeGradientMaxX");
	ShuriKenParticle3DShaderDeclaration.SOLSIZEGRADIENTYMAX = Shader3D.propertyNameToID("u_SOLSizeGradientMaxY");
	ShuriKenParticle3DShaderDeclaration.SOLSizeGradientZMAX = Shader3D.propertyNameToID("u_SOLSizeGradientMaxZ");
	ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYCONST = Shader3D.propertyNameToID("u_ROLAngularVelocityConst");
	ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYCONSTSEPRARATE = Shader3D.propertyNameToID("u_ROLAngularVelocityConstSeprarate");
	ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENT = Shader3D.propertyNameToID("u_ROLAngularVelocityGradient");
	ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENTX = Shader3D.propertyNameToID("u_ROLAngularVelocityGradientX");
	ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENTY = Shader3D.propertyNameToID("u_ROLAngularVelocityGradientY");
	ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENTZ = Shader3D.propertyNameToID("u_ROLAngularVelocityGradientZ");
	ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYCONSTMAX = Shader3D.propertyNameToID("u_ROLAngularVelocityConstMax");
	ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYCONSTMAXSEPRARATE = Shader3D.propertyNameToID("u_ROLAngularVelocityConstMaxSeprarate");
	ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENTMAX = Shader3D.propertyNameToID("u_ROLAngularVelocityGradientMax");
	ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENTXMAX = Shader3D.propertyNameToID("u_ROLAngularVelocityGradientMaxX");
	ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENTYMAX = Shader3D.propertyNameToID("u_ROLAngularVelocityGradientMaxY");
	ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENTZMAX = Shader3D.propertyNameToID("u_ROLAngularVelocityGradientMaxZ");
	ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENTWMAX = Shader3D.propertyNameToID("u_ROLAngularVelocityGradientMaxW");
	ShuriKenParticle3DShaderDeclaration.TEXTURESHEETANIMATIONCYCLES = Shader3D.propertyNameToID("u_TSACycles");
	ShuriKenParticle3DShaderDeclaration.TEXTURESHEETANIMATIONSUBUVLENGTH = Shader3D.propertyNameToID("u_TSASubUVLength");
	ShuriKenParticle3DShaderDeclaration.TEXTURESHEETANIMATIONGRADIENTUVS = Shader3D.propertyNameToID("u_TSAGradientUVs");
	ShuriKenParticle3DShaderDeclaration.TEXTURESHEETANIMATIONGRADIENTMAXUVS = Shader3D.propertyNameToID("u_TSAMaxGradientUVs");

	class ShurikenParticleRenderer extends BaseRender {
	    constructor(owner) {
	        super(owner);
	        this._finalGravity = new Vector3();
	        this._tempRotationMatrix = new Matrix4x4();
	        this._renderMode = 0;
	        this._mesh = null;
	        this.stretchedBillboardCameraSpeedScale = 0;
	        this.stretchedBillboardSpeedScale = 0;
	        this.stretchedBillboardLengthScale = 0;
	        this._defaultBoundBox = new BoundBox(new Vector3(), new Vector3());
	        this._renderMode = -1;
	        this.stretchedBillboardCameraSpeedScale = 0.0;
	        this.stretchedBillboardSpeedScale = 0.0;
	        this.stretchedBillboardLengthScale = 1.0;
	        this._supportOctree = false;
	    }
	    get renderMode() {
	        return this._renderMode;
	    }
	    get mesh() {
	        return this._mesh;
	    }
	    set mesh(value) {
	        if (this._mesh !== value) {
	            (this._mesh) && (this._mesh._removeReference());
	            this._mesh = value;
	            (value) && (value._addReference());
	            this._owner.particleSystem._initBufferDatas();
	        }
	    }
	    set renderMode(value) {
	        if (this._renderMode !== value) {
	            var defineDatas = this._shaderValues;
	            switch (this._renderMode) {
	                case 0:
	                    defineDatas.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_RENDERMODE_BILLBOARD);
	                    break;
	                case 1:
	                    defineDatas.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_RENDERMODE_STRETCHEDBILLBOARD);
	                    break;
	                case 2:
	                    defineDatas.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_RENDERMODE_HORIZONTALBILLBOARD);
	                    break;
	                case 3:
	                    defineDatas.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_RENDERMODE_VERTICALBILLBOARD);
	                    break;
	                case 4:
	                    defineDatas.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_RENDERMODE_MESH);
	                    break;
	            }
	            this._renderMode = value;
	            switch (value) {
	                case 0:
	                    defineDatas.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_RENDERMODE_BILLBOARD);
	                    break;
	                case 1:
	                    defineDatas.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_RENDERMODE_STRETCHEDBILLBOARD);
	                    break;
	                case 2:
	                    defineDatas.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_RENDERMODE_HORIZONTALBILLBOARD);
	                    break;
	                case 3:
	                    defineDatas.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_RENDERMODE_VERTICALBILLBOARD);
	                    break;
	                case 4:
	                    defineDatas.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_RENDERMODE_MESH);
	                    break;
	                default:
	                    throw new Error("ShurikenParticleRender: unknown renderMode Value.");
	            }
	            this._owner.particleSystem._initBufferDatas();
	        }
	    }
	    _calculateBoundingBox() {
	        var min = this._bounds.getMin();
	        min.x = -Number.MAX_VALUE;
	        min.y = -Number.MAX_VALUE;
	        min.z = -Number.MAX_VALUE;
	        this._bounds.setMin(min);
	        var max = this._bounds.getMax();
	        max.x = Number.MAX_VALUE;
	        max.y = Number.MAX_VALUE;
	        max.z = Number.MAX_VALUE;
	        this._bounds.setMax(max);
	        if (Laya.Render.supportWebGLPlusCulling) {
	            var min = this._bounds.getMin();
	            var max = this._bounds.getMax();
	            var buffer = FrustumCulling._cullingBuffer;
	            buffer[this._cullingBufferIndex + 1] = min.x;
	            buffer[this._cullingBufferIndex + 2] = min.y;
	            buffer[this._cullingBufferIndex + 3] = min.z;
	            buffer[this._cullingBufferIndex + 4] = max.x;
	            buffer[this._cullingBufferIndex + 5] = max.y;
	            buffer[this._cullingBufferIndex + 6] = max.z;
	        }
	    }
	    _needRender(boundFrustum, context) {
	        if (boundFrustum) {
	            if (boundFrustum.intersects(this.bounds._getBoundBox())) {
	                if (this._owner.particleSystem.isAlive)
	                    return true;
	                else
	                    return false;
	            }
	            else {
	                return false;
	            }
	        }
	        else {
	            return true;
	        }
	    }
	    _renderUpdate(context, transfrom) {
	        var particleSystem = this._owner.particleSystem;
	        var sv = this._shaderValues;
	        var transform = this._owner.transform;
	        switch (particleSystem.simulationSpace) {
	            case 0:
	                break;
	            case 1:
	                sv.setVector3(ShuriKenParticle3DShaderDeclaration.WORLDPOSITION, transform.position);
	                sv.setQuaternion(ShuriKenParticle3DShaderDeclaration.WORLDROTATION, transform.rotation);
	                break;
	            default:
	                throw new Error("ShurikenParticleMaterial: SimulationSpace value is invalid.");
	        }
	        switch (particleSystem.scaleMode) {
	            case 0:
	                var scale = transform.getWorldLossyScale();
	                sv.setVector3(ShuriKenParticle3DShaderDeclaration.POSITIONSCALE, scale);
	                sv.setVector3(ShuriKenParticle3DShaderDeclaration.SIZESCALE, scale);
	                break;
	            case 1:
	                var localScale = transform.localScale;
	                sv.setVector3(ShuriKenParticle3DShaderDeclaration.POSITIONSCALE, localScale);
	                sv.setVector3(ShuriKenParticle3DShaderDeclaration.SIZESCALE, localScale);
	                break;
	            case 2:
	                sv.setVector3(ShuriKenParticle3DShaderDeclaration.POSITIONSCALE, transform.getWorldLossyScale());
	                sv.setVector3(ShuriKenParticle3DShaderDeclaration.SIZESCALE, Vector3._ONE);
	                break;
	        }
	        Vector3.scale(Physics3DUtils.gravity, particleSystem.gravityModifier, this._finalGravity);
	        sv.setVector3(ShuriKenParticle3DShaderDeclaration.GRAVITY, this._finalGravity);
	        sv.setInt(ShuriKenParticle3DShaderDeclaration.SIMULATIONSPACE, particleSystem.simulationSpace);
	        sv.setBool(ShuriKenParticle3DShaderDeclaration.THREEDSTARTROTATION, particleSystem.threeDStartRotation);
	        sv.setInt(ShuriKenParticle3DShaderDeclaration.SCALINGMODE, particleSystem.scaleMode);
	        sv.setNumber(ShuriKenParticle3DShaderDeclaration.STRETCHEDBILLBOARDLENGTHSCALE, this.stretchedBillboardLengthScale);
	        sv.setNumber(ShuriKenParticle3DShaderDeclaration.STRETCHEDBILLBOARDSPEEDSCALE, this.stretchedBillboardSpeedScale);
	        sv.setNumber(ShuriKenParticle3DShaderDeclaration.CURRENTTIME, particleSystem._currentTime);
	    }
	    get bounds() {
	        if (this._boundsChange) {
	            this._calculateBoundingBox();
	            this._boundsChange = false;
	        }
	        return this._bounds;
	    }
	    _destroy() {
	        super._destroy();
	        (this._mesh) && (this._mesh._removeReference(), this._mesh = null);
	    }
	}

	class VertexShuriKenParticle {
	    constructor() {
	    }
	}
	VertexShuriKenParticle.PARTICLE_CORNERTEXTURECOORDINATE0 = 0;
	VertexShuriKenParticle.PARTICLE_POSITION0 = 1;
	VertexShuriKenParticle.PARTICLE_COLOR0 = 2;
	VertexShuriKenParticle.PARTICLE_TEXTURECOORDINATE0 = 3;
	VertexShuriKenParticle.PARTICLE_SHAPEPOSITIONSTARTLIFETIME = 4;
	VertexShuriKenParticle.PARTICLE_DIRECTIONTIME = 5;
	VertexShuriKenParticle.PARTICLE_STARTCOLOR0 = 6;
	VertexShuriKenParticle.PARTICLE_ENDCOLOR0 = 7;
	VertexShuriKenParticle.PARTICLE_STARTSIZE = 8;
	VertexShuriKenParticle.PARTICLE_STARTROTATION = 9;
	VertexShuriKenParticle.PARTICLE_STARTSPEED = 10;
	VertexShuriKenParticle.PARTICLE_RANDOM0 = 11;
	VertexShuriKenParticle.PARTICLE_RANDOM1 = 12;
	VertexShuriKenParticle.PARTICLE_SIMULATIONWORLDPOSTION = 13;
	VertexShuriKenParticle.PARTICLE_SIMULATIONWORLDROTATION = 14;

	class VertexShurikenParticleBillboard extends VertexShuriKenParticle {
	    static get vertexDeclaration() {
	        return VertexShurikenParticleBillboard._vertexDeclaration;
	    }
	    static __init__() {
	        VertexShurikenParticleBillboard._vertexDeclaration = new VertexDeclaration(152, [new VertexElement(0, VertexElementFormat.Vector4, VertexShuriKenParticle.PARTICLE_CORNERTEXTURECOORDINATE0),
	            new VertexElement(16, VertexElementFormat.Vector4, VertexShuriKenParticle.PARTICLE_SHAPEPOSITIONSTARTLIFETIME),
	            new VertexElement(32, VertexElementFormat.Vector4, VertexShuriKenParticle.PARTICLE_DIRECTIONTIME),
	            new VertexElement(48, VertexElementFormat.Vector4, VertexShuriKenParticle.PARTICLE_STARTCOLOR0),
	            new VertexElement(64, VertexElementFormat.Vector3, VertexShuriKenParticle.PARTICLE_STARTSIZE),
	            new VertexElement(76, VertexElementFormat.Vector3, VertexShuriKenParticle.PARTICLE_STARTROTATION),
	            new VertexElement(88, VertexElementFormat.Single, VertexShuriKenParticle.PARTICLE_STARTSPEED),
	            new VertexElement(92, VertexElementFormat.Vector4, VertexShuriKenParticle.PARTICLE_RANDOM0),
	            new VertexElement(108, VertexElementFormat.Vector4, VertexShuriKenParticle.PARTICLE_RANDOM1),
	            new VertexElement(124, VertexElementFormat.Vector3, VertexShuriKenParticle.PARTICLE_SIMULATIONWORLDPOSTION),
	            new VertexElement(136, VertexElementFormat.Vector4, VertexShuriKenParticle.PARTICLE_SIMULATIONWORLDROTATION)]);
	    }
	    get cornerTextureCoordinate() {
	        return this._cornerTextureCoordinate;
	    }
	    get positionStartLifeTime() {
	        return this._positionStartLifeTime;
	    }
	    get velocity() {
	        return this._velocity;
	    }
	    get startColor() {
	        return this._startColor;
	    }
	    get startSize() {
	        return this._startSize;
	    }
	    get startRotation0() {
	        return this._startRotation0;
	    }
	    get startRotation1() {
	        return this._startRotation1;
	    }
	    get startRotation2() {
	        return this._startRotation2;
	    }
	    get startLifeTime() {
	        return this._startLifeTime;
	    }
	    get time() {
	        return this._time;
	    }
	    get startSpeed() {
	        return this._startSpeed;
	    }
	    get random0() {
	        return this._randoms0;
	    }
	    get random1() {
	        return this._randoms1;
	    }
	    get simulationWorldPostion() {
	        return this._simulationWorldPostion;
	    }
	    constructor(cornerTextureCoordinate, positionStartLifeTime, velocity, startColor, startSize, startRotation0, startRotation1, startRotation2, ageAddScale, time, startSpeed, randoms0, randoms1, simulationWorldPostion) {
	        super();
	        this._cornerTextureCoordinate = cornerTextureCoordinate;
	        this._positionStartLifeTime = positionStartLifeTime;
	        this._velocity = velocity;
	        this._startColor = startColor;
	        this._startSize = startSize;
	        this._startRotation0 = startRotation0;
	        this._startRotation1 = startRotation1;
	        this._startRotation2 = startRotation2;
	        this._startLifeTime = ageAddScale;
	        this._time = time;
	        this._startSpeed = startSpeed;
	        this._randoms0 = this.random0;
	        this._randoms1 = this.random1;
	        this._simulationWorldPostion = simulationWorldPostion;
	    }
	}

	class VertexShurikenParticleMesh extends VertexShuriKenParticle {
	    static __init__() {
	        VertexShurikenParticleMesh._vertexDeclaration = new VertexDeclaration(172, [new VertexElement(0, VertexElementFormat.Vector3, VertexShuriKenParticle.PARTICLE_POSITION0),
	            new VertexElement(12, VertexElementFormat.Vector4, VertexShuriKenParticle.PARTICLE_COLOR0),
	            new VertexElement(28, VertexElementFormat.Vector2, VertexShuriKenParticle.PARTICLE_TEXTURECOORDINATE0),
	            new VertexElement(36, VertexElementFormat.Vector4, VertexShuriKenParticle.PARTICLE_SHAPEPOSITIONSTARTLIFETIME),
	            new VertexElement(52, VertexElementFormat.Vector4, VertexShuriKenParticle.PARTICLE_DIRECTIONTIME),
	            new VertexElement(68, VertexElementFormat.Vector4, VertexShuriKenParticle.PARTICLE_STARTCOLOR0),
	            new VertexElement(84, VertexElementFormat.Vector3, VertexShuriKenParticle.PARTICLE_STARTSIZE),
	            new VertexElement(96, VertexElementFormat.Vector3, VertexShuriKenParticle.PARTICLE_STARTROTATION),
	            new VertexElement(108, VertexElementFormat.Single, VertexShuriKenParticle.PARTICLE_STARTSPEED),
	            new VertexElement(112, VertexElementFormat.Vector4, VertexShuriKenParticle.PARTICLE_RANDOM0),
	            new VertexElement(128, VertexElementFormat.Vector4, VertexShuriKenParticle.PARTICLE_RANDOM1),
	            new VertexElement(144, VertexElementFormat.Vector3, VertexShuriKenParticle.PARTICLE_SIMULATIONWORLDPOSTION),
	            new VertexElement(156, VertexElementFormat.Vector4, VertexShuriKenParticle.PARTICLE_SIMULATIONWORLDROTATION)]);
	    }
	    static get vertexDeclaration() {
	        return VertexShurikenParticleMesh._vertexDeclaration;
	    }
	    get cornerTextureCoordinate() {
	        return this._cornerTextureCoordinate;
	    }
	    get position() {
	        return this._positionStartLifeTime;
	    }
	    get velocity() {
	        return this._velocity;
	    }
	    get startColor() {
	        return this._startColor;
	    }
	    get startSize() {
	        return this._startSize;
	    }
	    get startRotation0() {
	        return this._startRotation0;
	    }
	    get startRotation1() {
	        return this._startRotation1;
	    }
	    get startRotation2() {
	        return this._startRotation2;
	    }
	    get startLifeTime() {
	        return this._startLifeTime;
	    }
	    get time() {
	        return this._time;
	    }
	    get startSpeed() {
	        return this._startSpeed;
	    }
	    get random0() {
	        return this._randoms0;
	    }
	    get random1() {
	        return this._randoms1;
	    }
	    get simulationWorldPostion() {
	        return this._simulationWorldPostion;
	    }
	    constructor(cornerTextureCoordinate, positionStartLifeTime, velocity, startColor, startSize, startRotation0, startRotation1, startRotation2, ageAddScale, time, startSpeed, randoms0, randoms1, simulationWorldPostion) {
	        super();
	        this._cornerTextureCoordinate = cornerTextureCoordinate;
	        this._positionStartLifeTime = positionStartLifeTime;
	        this._velocity = velocity;
	        this._startColor = startColor;
	        this._startSize = startSize;
	        this._startRotation0 = startRotation0;
	        this._startRotation1 = startRotation1;
	        this._startRotation2 = startRotation2;
	        this._startLifeTime = ageAddScale;
	        this._time = time;
	        this._startSpeed = startSpeed;
	        this._randoms0 = this.random0;
	        this._randoms1 = this.random1;
	        this._simulationWorldPostion = simulationWorldPostion;
	    }
	}

	class BoundSphere {
	    constructor(center, radius) {
	        this.center = center;
	        this.radius = radius;
	    }
	    toDefault() {
	        this.center.toDefault();
	        this.radius = 0;
	    }
	    static createFromSubPoints(points, start, count, out) {
	        if (points == null) {
	            throw new Error("points");
	        }
	        if (start < 0 || start >= points.length) {
	            throw new Error("start" + start + "Must be in the range [0, " + (points.length - 1) + "]");
	        }
	        if (count < 0 || (start + count) > points.length) {
	            throw new Error("count" + count + "Must be in the range <= " + points.length + "}");
	        }
	        var upperEnd = start + count;
	        var center = BoundSphere._tempVector3;
	        center.x = 0;
	        center.y = 0;
	        center.z = 0;
	        for (var i = start; i < upperEnd; ++i) {
	            Vector3.add(points[i], center, center);
	        }
	        var outCenter = out.center;
	        Vector3.scale(center, 1 / count, outCenter);
	        var radius = 0.0;
	        for (i = start; i < upperEnd; ++i) {
	            var distance = Vector3.distanceSquared(outCenter, points[i]);
	            if (distance > radius)
	                radius = distance;
	        }
	        out.radius = Math.sqrt(radius);
	    }
	    static createfromPoints(points, out) {
	        if (points == null) {
	            throw new Error("points");
	        }
	        BoundSphere.createFromSubPoints(points, 0, points.length, out);
	    }
	    intersectsRayDistance(ray) {
	        return CollisionUtils.intersectsRayAndSphereRD(ray, this);
	    }
	    intersectsRayPoint(ray, outPoint) {
	        return CollisionUtils.intersectsRayAndSphereRP(ray, this, outPoint);
	    }
	    cloneTo(destObject) {
	        var dest = destObject;
	        this.center.cloneTo(dest.center);
	        dest.radius = this.radius;
	    }
	    clone() {
	        var dest = new BoundSphere(new Vector3(), 0);
	        this.cloneTo(dest);
	        return dest;
	    }
	}
	BoundSphere._tempVector3 = new Vector3();

	class Rand {
	    constructor(seed) {
	        this._temp = new Uint32Array(1);
	        this.seeds = new Uint32Array(4);
	        this.seeds[0] = seed;
	        this.seeds[1] = this.seeds[0] * 0x6C078965 + 1;
	        this.seeds[2] = this.seeds[1] * 0x6C078965 + 1;
	        this.seeds[3] = this.seeds[2] * 0x6C078965 + 1;
	    }
	    static getFloatFromInt(v) {
	        return (v & 0x007FFFFF) * (1.0 / 8388607.0);
	    }
	    static getByteFromInt(v) {
	        return (v & 0x007FFFFF) >>> 15;
	    }
	    get seed() {
	        return this.seeds[0];
	    }
	    set seed(seed) {
	        this.seeds[0] = seed;
	        this.seeds[1] = this.seeds[0] * 0x6C078965 + 1;
	        this.seeds[2] = this.seeds[1] * 0x6C078965 + 1;
	        this.seeds[3] = this.seeds[2] * 0x6C078965 + 1;
	    }
	    getUint() {
	        this._temp[0] = this.seeds[0] ^ (this.seeds[0] << 11);
	        this.seeds[0] = this.seeds[1];
	        this.seeds[1] = this.seeds[2];
	        this.seeds[2] = this.seeds[3];
	        this.seeds[3] = (this.seeds[3] ^ (this.seeds[3] >>> 19)) ^ (this._temp[0] ^ (this._temp[0] >>> 8));
	        return this.seeds[3];
	    }
	    getFloat() {
	        this.getUint();
	        return (this.seeds[3] & 0x007FFFFF) * (1.0 / 8388607.0);
	    }
	    getSignedFloat() {
	        return this.getFloat() * 2.0 - 1.0;
	    }
	}

	class Emission {
	    set emissionRate(value) {
	        if (value < 0)
	            throw new Error("ParticleBaseShape:emissionRate value must large or equal than 0.");
	        this._emissionRate = value;
	    }
	    get emissionRate() {
	        return this._emissionRate;
	    }
	    get destroyed() {
	        return this._destroyed;
	    }
	    constructor() {
	        this._destroyed = false;
	        this.emissionRate = 10;
	        this._bursts = [];
	    }
	    destroy() {
	        this._bursts = null;
	        this._destroyed = true;
	    }
	    getBurstsCount() {
	        return this._bursts.length;
	    }
	    getBurstByIndex(index) {
	        return this._bursts[index];
	    }
	    addBurst(burst) {
	        var burstsCount = this._bursts.length;
	        if (burstsCount > 0)
	            for (var i = 0; i < burstsCount; i++) {
	                if (this._bursts[i].time > burst.time)
	                    this._bursts.splice(i, 0, burst);
	            }
	        this._bursts.push(burst);
	    }
	    removeBurst(burst) {
	        var index = this._bursts.indexOf(burst);
	        if (index !== -1) {
	            this._bursts.splice(index, 1);
	        }
	    }
	    removeBurstByIndex(index) {
	        this._bursts.splice(index, 1);
	    }
	    clearBurst() {
	        this._bursts.length = 0;
	    }
	    cloneTo(destObject) {
	        var destEmission = destObject;
	        var destBursts = destEmission._bursts;
	        destBursts.length = this._bursts.length;
	        for (var i = 0, n = this._bursts.length; i < n; i++) {
	            var destBurst = destBursts[i];
	            if (destBurst)
	                this._bursts[i].cloneTo(destBurst);
	            else
	                destBursts[i] = this._bursts[i].clone();
	        }
	        destEmission._emissionRate = this._emissionRate;
	        destEmission.enbale = this.enbale;
	    }
	    clone() {
	        var destEmission = new Emission();
	        this.cloneTo(destEmission);
	        return destEmission;
	    }
	}

	class GradientDataNumber {
	    constructor() {
	        this._currentLength = 0;
	        this._elements = new Float32Array(8);
	    }
	    get gradientCount() {
	        return this._currentLength / 2;
	    }
	    add(key, value) {
	        if (this._currentLength < 8) {
	            if ((this._currentLength === 6) && ((key !== 1))) {
	                key = 1;
	                console.log("GradientDataNumber warning:the forth key is  be force set to 1.");
	            }
	            this._elements[this._currentLength++] = key;
	            this._elements[this._currentLength++] = value;
	        }
	        else {
	            console.log("GradientDataNumber warning:data count must lessEqual than 4");
	        }
	    }
	    getKeyByIndex(index) {
	        return this._elements[index * 2];
	    }
	    getValueByIndex(index) {
	        return this._elements[index * 2 + 1];
	    }
	    getAverageValue() {
	        var total = 0;
	        for (var i = 0, n = this._currentLength - 2; i < n; i += 2) {
	            var subValue = this._elements[i + 1];
	            subValue += this._elements[i + 3];
	            subValue = subValue * (this._elements[i + 2] - this._elements[i]);
	        }
	        return total / 2;
	    }
	    cloneTo(destObject) {
	        var destGradientDataNumber = destObject;
	        destGradientDataNumber._currentLength = this._currentLength;
	        var destElements = destGradientDataNumber._elements;
	        for (var i = 0, n = this._elements.length; i < n; i++)
	            destElements[i] = this._elements[i];
	    }
	    clone() {
	        var destGradientDataNumber = new GradientDataNumber();
	        this.cloneTo(destGradientDataNumber);
	        return destGradientDataNumber;
	    }
	}

	class ShurikenParticleData {
	    constructor() {
	    }
	    static _getStartLifetimeFromGradient(startLifeTimeGradient, emissionTime) {
	        for (var i = 1, n = startLifeTimeGradient.gradientCount; i < n; i++) {
	            var key = startLifeTimeGradient.getKeyByIndex(i);
	            if (key >= emissionTime) {
	                var lastKey = startLifeTimeGradient.getKeyByIndex(i - 1);
	                var age = (emissionTime - lastKey) / (key - lastKey);
	                return Laya.MathUtil.lerp(startLifeTimeGradient.getValueByIndex(i - 1), startLifeTimeGradient.getValueByIndex(i), age);
	            }
	        }
	        throw new Error("ShurikenParticleData: can't get value foam startLifeTimeGradient.");
	    }
	    static _randomInvertRoationArray(rotatonE, outE, randomizeRotationDirection, rand, randomSeeds) {
	        var randDic;
	        if (rand) {
	            rand.seed = randomSeeds[6];
	            randDic = rand.getFloat();
	            randomSeeds[6] = rand.seed;
	        }
	        else {
	            randDic = Math.random();
	        }
	        if (randDic < randomizeRotationDirection) {
	            outE.x = -rotatonE.x;
	            outE.y = -rotatonE.y;
	            outE.z = -rotatonE.z;
	        }
	        else {
	            outE.x = rotatonE.x;
	            outE.y = rotatonE.y;
	            outE.z = rotatonE.z;
	        }
	    }
	    static _randomInvertRoation(rotaton, randomizeRotationDirection, rand, randomSeeds) {
	        var randDic;
	        if (rand) {
	            rand.seed = randomSeeds[6];
	            randDic = rand.getFloat();
	            randomSeeds[6] = rand.seed;
	        }
	        else {
	            randDic = Math.random();
	        }
	        if (randDic < randomizeRotationDirection)
	            rotaton = -rotaton;
	        return rotaton;
	    }
	    static create(particleSystem, particleRender, transform) {
	        var autoRandomSeed = particleSystem.autoRandomSeed;
	        var rand = particleSystem._rand;
	        var randomSeeds = particleSystem._randomSeeds;
	        switch (particleSystem.startColorType) {
	            case 0:
	                var constantStartColor = particleSystem.startColorConstant;
	                ShurikenParticleData.startColor.x = constantStartColor.x;
	                ShurikenParticleData.startColor.y = constantStartColor.y;
	                ShurikenParticleData.startColor.z = constantStartColor.z;
	                ShurikenParticleData.startColor.w = constantStartColor.w;
	                break;
	            case 2:
	                if (autoRandomSeed) {
	                    Vector4.lerp(particleSystem.startColorConstantMin, particleSystem.startColorConstantMax, Math.random(), ShurikenParticleData.startColor);
	                }
	                else {
	                    rand.seed = randomSeeds[3];
	                    Vector4.lerp(particleSystem.startColorConstantMin, particleSystem.startColorConstantMax, rand.getFloat(), ShurikenParticleData.startColor);
	                    randomSeeds[3] = rand.seed;
	                }
	                break;
	        }
	        var colorOverLifetime = particleSystem.colorOverLifetime;
	        if (colorOverLifetime && colorOverLifetime.enbale) {
	            var color = colorOverLifetime.color;
	            switch (color.type) {
	                case 0:
	                    ShurikenParticleData.startColor.x = ShurikenParticleData.startColor.x * color.constant.x;
	                    ShurikenParticleData.startColor.y = ShurikenParticleData.startColor.y * color.constant.y;
	                    ShurikenParticleData.startColor.z = ShurikenParticleData.startColor.z * color.constant.z;
	                    ShurikenParticleData.startColor.w = ShurikenParticleData.startColor.w * color.constant.w;
	                    break;
	                case 2:
	                    var colorRandom;
	                    if (autoRandomSeed) {
	                        colorRandom = Math.random();
	                    }
	                    else {
	                        rand.seed = randomSeeds[10];
	                        colorRandom = rand.getFloat();
	                        randomSeeds[10] = rand.seed;
	                    }
	                    var minConstantColor = color.constantMin;
	                    var maxConstantColor = color.constantMax;
	                    ShurikenParticleData.startColor.x = ShurikenParticleData.startColor.x * Laya.MathUtil.lerp(minConstantColor.x, maxConstantColor.x, colorRandom);
	                    ShurikenParticleData.startColor.y = ShurikenParticleData.startColor.y * Laya.MathUtil.lerp(minConstantColor.y, maxConstantColor.y, colorRandom);
	                    ShurikenParticleData.startColor.z = ShurikenParticleData.startColor.z * Laya.MathUtil.lerp(minConstantColor.z, maxConstantColor.z, colorRandom);
	                    ShurikenParticleData.startColor.w = ShurikenParticleData.startColor.w * Laya.MathUtil.lerp(minConstantColor.w, maxConstantColor.w, colorRandom);
	                    break;
	            }
	        }
	        var particleSize = ShurikenParticleData.startSize;
	        switch (particleSystem.startSizeType) {
	            case 0:
	                if (particleSystem.threeDStartSize) {
	                    var startSizeConstantSeparate = particleSystem.startSizeConstantSeparate;
	                    particleSize[0] = startSizeConstantSeparate.x;
	                    particleSize[1] = startSizeConstantSeparate.y;
	                    particleSize[2] = startSizeConstantSeparate.z;
	                }
	                else {
	                    particleSize[0] = particleSize[1] = particleSize[2] = particleSystem.startSizeConstant;
	                }
	                break;
	            case 2:
	                if (particleSystem.threeDStartSize) {
	                    var startSizeConstantMinSeparate = particleSystem.startSizeConstantMinSeparate;
	                    var startSizeConstantMaxSeparate = particleSystem.startSizeConstantMaxSeparate;
	                    if (autoRandomSeed) {
	                        particleSize[0] = Laya.MathUtil.lerp(startSizeConstantMinSeparate.x, startSizeConstantMaxSeparate.x, Math.random());
	                        particleSize[1] = Laya.MathUtil.lerp(startSizeConstantMinSeparate.y, startSizeConstantMaxSeparate.y, Math.random());
	                        particleSize[2] = Laya.MathUtil.lerp(startSizeConstantMinSeparate.z, startSizeConstantMaxSeparate.z, Math.random());
	                    }
	                    else {
	                        rand.seed = randomSeeds[4];
	                        particleSize[0] = Laya.MathUtil.lerp(startSizeConstantMinSeparate.x, startSizeConstantMaxSeparate.x, rand.getFloat());
	                        particleSize[1] = Laya.MathUtil.lerp(startSizeConstantMinSeparate.y, startSizeConstantMaxSeparate.y, rand.getFloat());
	                        particleSize[2] = Laya.MathUtil.lerp(startSizeConstantMinSeparate.z, startSizeConstantMaxSeparate.z, rand.getFloat());
	                        randomSeeds[4] = rand.seed;
	                    }
	                }
	                else {
	                    if (autoRandomSeed) {
	                        particleSize[0] = particleSize[1] = particleSize[2] = Laya.MathUtil.lerp(particleSystem.startSizeConstantMin, particleSystem.startSizeConstantMax, Math.random());
	                    }
	                    else {
	                        rand.seed = randomSeeds[4];
	                        particleSize[0] = particleSize[1] = particleSize[2] = Laya.MathUtil.lerp(particleSystem.startSizeConstantMin, particleSystem.startSizeConstantMax, rand.getFloat());
	                        randomSeeds[4] = rand.seed;
	                    }
	                }
	                break;
	        }
	        var sizeOverLifetime = particleSystem.sizeOverLifetime;
	        if (sizeOverLifetime && sizeOverLifetime.enbale && sizeOverLifetime.size.type === 1) {
	            var size = sizeOverLifetime.size;
	            if (size.separateAxes) {
	                if (autoRandomSeed) {
	                    particleSize[0] = particleSize[0] * Laya.MathUtil.lerp(size.constantMinSeparate.x, size.constantMaxSeparate.x, Math.random());
	                    particleSize[1] = particleSize[1] * Laya.MathUtil.lerp(size.constantMinSeparate.y, size.constantMaxSeparate.y, Math.random());
	                    particleSize[2] = particleSize[2] * Laya.MathUtil.lerp(size.constantMinSeparate.z, size.constantMaxSeparate.z, Math.random());
	                }
	                else {
	                    rand.seed = randomSeeds[11];
	                    particleSize[0] = particleSize[0] * Laya.MathUtil.lerp(size.constantMinSeparate.x, size.constantMaxSeparate.x, rand.getFloat());
	                    particleSize[1] = particleSize[1] * Laya.MathUtil.lerp(size.constantMinSeparate.y, size.constantMaxSeparate.y, rand.getFloat());
	                    particleSize[2] = particleSize[2] * Laya.MathUtil.lerp(size.constantMinSeparate.z, size.constantMaxSeparate.z, rand.getFloat());
	                    randomSeeds[11] = rand.seed;
	                }
	            }
	            else {
	                var randomSize;
	                if (autoRandomSeed) {
	                    randomSize = Laya.MathUtil.lerp(size.constantMin, size.constantMax, Math.random());
	                }
	                else {
	                    rand.seed = randomSeeds[11];
	                    randomSize = Laya.MathUtil.lerp(size.constantMin, size.constantMax, rand.getFloat());
	                    randomSeeds[11] = rand.seed;
	                }
	                particleSize[0] = particleSize[0] * randomSize;
	                particleSize[1] = particleSize[1] * randomSize;
	                particleSize[2] = particleSize[2] * randomSize;
	            }
	        }
	        var renderMode = particleRender.renderMode;
	        if (renderMode !== 1) {
	            switch (particleSystem.startRotationType) {
	                case 0:
	                    if (particleSystem.threeDStartRotation) {
	                        var startRotationConstantSeparate = particleSystem.startRotationConstantSeparate;
	                        var randomRotationE = ShurikenParticleData._tempVector30;
	                        ShurikenParticleData._randomInvertRoationArray(startRotationConstantSeparate, randomRotationE, particleSystem.randomizeRotationDirection, autoRandomSeed ? null : rand, randomSeeds);
	                        ShurikenParticleData.startRotation[0] = randomRotationE.x;
	                        ShurikenParticleData.startRotation[1] = randomRotationE.y;
	                        if (renderMode !== 4)
	                            ShurikenParticleData.startRotation[2] = -randomRotationE.z;
	                        else
	                            ShurikenParticleData.startRotation[2] = randomRotationE.z;
	                    }
	                    else {
	                        ShurikenParticleData.startRotation[0] = ShurikenParticleData._randomInvertRoation(particleSystem.startRotationConstant, particleSystem.randomizeRotationDirection, autoRandomSeed ? null : rand, randomSeeds);
	                        ShurikenParticleData.startRotation[1] = 0;
	                        ShurikenParticleData.startRotation[2] = 0;
	                    }
	                    break;
	                case 2:
	                    if (particleSystem.threeDStartRotation) {
	                        var startRotationConstantMinSeparate = particleSystem.startRotationConstantMinSeparate;
	                        var startRotationConstantMaxSeparate = particleSystem.startRotationConstantMaxSeparate;
	                        var lerpRoationE = ShurikenParticleData._tempVector30;
	                        if (autoRandomSeed) {
	                            lerpRoationE.x = Laya.MathUtil.lerp(startRotationConstantMinSeparate.x, startRotationConstantMaxSeparate.x, Math.random());
	                            lerpRoationE.y = Laya.MathUtil.lerp(startRotationConstantMinSeparate.y, startRotationConstantMaxSeparate.y, Math.random());
	                            lerpRoationE.z = Laya.MathUtil.lerp(startRotationConstantMinSeparate.z, startRotationConstantMaxSeparate.z, Math.random());
	                        }
	                        else {
	                            rand.seed = randomSeeds[5];
	                            lerpRoationE.x = Laya.MathUtil.lerp(startRotationConstantMinSeparate.x, startRotationConstantMaxSeparate.x, rand.getFloat());
	                            lerpRoationE.y = Laya.MathUtil.lerp(startRotationConstantMinSeparate.y, startRotationConstantMaxSeparate.y, rand.getFloat());
	                            lerpRoationE.z = Laya.MathUtil.lerp(startRotationConstantMinSeparate.z, startRotationConstantMaxSeparate.z, rand.getFloat());
	                            randomSeeds[5] = rand.seed;
	                        }
	                        ShurikenParticleData._randomInvertRoationArray(lerpRoationE, lerpRoationE, particleSystem.randomizeRotationDirection, autoRandomSeed ? null : rand, randomSeeds);
	                        ShurikenParticleData.startRotation[0] = lerpRoationE.x;
	                        ShurikenParticleData.startRotation[1] = lerpRoationE.y;
	                        if (renderMode !== 4)
	                            ShurikenParticleData.startRotation[2] = -lerpRoationE.z;
	                        else
	                            ShurikenParticleData.startRotation[2] = lerpRoationE.z;
	                    }
	                    else {
	                        if (autoRandomSeed) {
	                            ShurikenParticleData.startRotation[0] = ShurikenParticleData._randomInvertRoation(Laya.MathUtil.lerp(particleSystem.startRotationConstantMin, particleSystem.startRotationConstantMax, Math.random()), particleSystem.randomizeRotationDirection, autoRandomSeed ? null : rand, randomSeeds);
	                        }
	                        else {
	                            rand.seed = randomSeeds[5];
	                            ShurikenParticleData.startRotation[0] = ShurikenParticleData._randomInvertRoation(Laya.MathUtil.lerp(particleSystem.startRotationConstantMin, particleSystem.startRotationConstantMax, rand.getFloat()), particleSystem.randomizeRotationDirection, autoRandomSeed ? null : rand, randomSeeds);
	                            randomSeeds[5] = rand.seed;
	                        }
	                    }
	                    break;
	            }
	        }
	        switch (particleSystem.startLifetimeType) {
	            case 0:
	                ShurikenParticleData.startLifeTime = particleSystem.startLifetimeConstant;
	                break;
	            case 1:
	                ShurikenParticleData.startLifeTime = ShurikenParticleData._getStartLifetimeFromGradient(particleSystem.startLifeTimeGradient, particleSystem.emissionTime);
	                break;
	            case 2:
	                if (autoRandomSeed) {
	                    ShurikenParticleData.startLifeTime = Laya.MathUtil.lerp(particleSystem.startLifetimeConstantMin, particleSystem.startLifetimeConstantMax, Math.random());
	                }
	                else {
	                    rand.seed = randomSeeds[7];
	                    ShurikenParticleData.startLifeTime = Laya.MathUtil.lerp(particleSystem.startLifetimeConstantMin, particleSystem.startLifetimeConstantMax, rand.getFloat());
	                    randomSeeds[7] = rand.seed;
	                }
	                break;
	            case 3:
	                var emissionTime = particleSystem.emissionTime;
	                if (autoRandomSeed) {
	                    ShurikenParticleData.startLifeTime = Laya.MathUtil.lerp(ShurikenParticleData._getStartLifetimeFromGradient(particleSystem.startLifeTimeGradientMin, emissionTime), ShurikenParticleData._getStartLifetimeFromGradient(particleSystem.startLifeTimeGradientMax, emissionTime), Math.random());
	                }
	                else {
	                    rand.seed = randomSeeds[7];
	                    ShurikenParticleData.startLifeTime = Laya.MathUtil.lerp(ShurikenParticleData._getStartLifetimeFromGradient(particleSystem.startLifeTimeGradientMin, emissionTime), ShurikenParticleData._getStartLifetimeFromGradient(particleSystem.startLifeTimeGradientMax, emissionTime), rand.getFloat());
	                    randomSeeds[7] = rand.seed;
	                }
	                break;
	        }
	        var textureSheetAnimation = particleSystem.textureSheetAnimation;
	        var enableSheetAnimation = textureSheetAnimation && textureSheetAnimation.enable;
	        if (enableSheetAnimation) {
	            var title = textureSheetAnimation.tiles;
	            var titleX = title.x, titleY = title.y;
	            var subU = 1.0 / titleX, subV = 1.0 / titleY;
	            var startFrameCount;
	            var startFrame = textureSheetAnimation.startFrame;
	            switch (startFrame.type) {
	                case 0:
	                    startFrameCount = startFrame.constant;
	                    break;
	                case 1:
	                    if (autoRandomSeed) {
	                        startFrameCount = Laya.MathUtil.lerp(startFrame.constantMin, startFrame.constantMax, Math.random());
	                    }
	                    else {
	                        rand.seed = randomSeeds[14];
	                        startFrameCount = Laya.MathUtil.lerp(startFrame.constantMin, startFrame.constantMax, rand.getFloat());
	                        randomSeeds[14] = rand.seed;
	                    }
	                    break;
	            }
	            var frame = textureSheetAnimation.frame;
	            var cycles = textureSheetAnimation.cycles;
	            switch (frame.type) {
	                case 0:
	                    startFrameCount += frame.constant * cycles;
	                    break;
	                case 2:
	                    if (autoRandomSeed) {
	                        startFrameCount += Laya.MathUtil.lerp(frame.constantMin, frame.constantMax, Math.random()) * cycles;
	                    }
	                    else {
	                        rand.seed = randomSeeds[15];
	                        startFrameCount += Laya.MathUtil.lerp(frame.constantMin, frame.constantMax, rand.getFloat()) * cycles;
	                        randomSeeds[15] = rand.seed;
	                    }
	                    break;
	            }
	            var startRow = 0;
	            switch (textureSheetAnimation.type) {
	                case 0:
	                    startRow = Math.floor(startFrameCount / titleX);
	                    break;
	                case 1:
	                    if (textureSheetAnimation.randomRow) {
	                        if (autoRandomSeed) {
	                            startRow = Math.floor(Math.random() * titleY);
	                        }
	                        else {
	                            rand.seed = randomSeeds[13];
	                            startRow = Math.floor(rand.getFloat() * titleY);
	                            randomSeeds[13] = rand.seed;
	                        }
	                    }
	                    else {
	                        startRow = textureSheetAnimation.rowIndex;
	                    }
	                    break;
	            }
	            var startCol = Math.floor(startFrameCount % titleX);
	            ShurikenParticleData.startUVInfo = ShurikenParticleData.startUVInfo;
	            ShurikenParticleData.startUVInfo[0] = subU;
	            ShurikenParticleData.startUVInfo[1] = subV;
	            ShurikenParticleData.startUVInfo[2] = startCol * subU;
	            ShurikenParticleData.startUVInfo[3] = startRow * subV;
	        }
	        else {
	            ShurikenParticleData.startUVInfo = ShurikenParticleData.startUVInfo;
	            ShurikenParticleData.startUVInfo[0] = 1.0;
	            ShurikenParticleData.startUVInfo[1] = 1.0;
	            ShurikenParticleData.startUVInfo[2] = 0.0;
	            ShurikenParticleData.startUVInfo[3] = 0.0;
	        }
	    }
	}
	ShurikenParticleData._tempVector30 = new Vector3();
	ShurikenParticleData.startColor = new Vector4();
	ShurikenParticleData.startSize = new Float32Array(3);
	ShurikenParticleData.startRotation = new Float32Array(3);
	ShurikenParticleData.startUVInfo = new Float32Array(4);

	class ShurikenParticleSystem extends GeometryElement {
	    constructor(owner) {
	        super();
	        this._tempRotationMatrix = new Matrix4x4();
	        this._boundingSphere = null;
	        this._boundingBox = null;
	        this._boundingBoxCorners = null;
	        this._owner = null;
	        this._ownerRender = null;
	        this._vertices = null;
	        this._floatCountPerVertex = 0;
	        this._startLifeTimeIndex = 0;
	        this._timeIndex = 0;
	        this._simulateUpdate = false;
	        this._firstActiveElement = 0;
	        this._firstNewElement = 0;
	        this._firstFreeElement = 0;
	        this._firstRetiredElement = 0;
	        this._drawCounter = 0;
	        this._bufferMaxParticles = 0;
	        this._emission = null;
	        this._shape = null;
	        this._isEmitting = false;
	        this._isPlaying = false;
	        this._isPaused = false;
	        this._playStartDelay = 0;
	        this._frameRateTime = 0;
	        this._emissionTime = 0;
	        this._totalDelayTime = 0;
	        this._burstsIndex = 0;
	        this._velocityOverLifetime = null;
	        this._colorOverLifetime = null;
	        this._sizeOverLifetime = null;
	        this._rotationOverLifetime = null;
	        this._textureSheetAnimation = null;
	        this._startLifetimeType = 0;
	        this._startLifetimeConstant = 0;
	        this._startLifeTimeGradient = null;
	        this._startLifetimeConstantMin = 0;
	        this._startLifetimeConstantMax = 0;
	        this._startLifeTimeGradientMin = null;
	        this._startLifeTimeGradientMax = null;
	        this._maxStartLifetime = 0;
	        this._uvLength = new Vector2();
	        this._vertexStride = 0;
	        this._indexStride = 0;
	        this._vertexBuffer = null;
	        this._indexBuffer = null;
	        this._bufferState = new BufferState();
	        this._currentTime = 0;
	        this._startUpdateLoopCount = 0;
	        this._rand = null;
	        this._randomSeeds = null;
	        this.duration = 0;
	        this.looping = false;
	        this.prewarm = false;
	        this.startDelayType = 0;
	        this.startDelay = 0;
	        this.startDelayMin = 0;
	        this.startDelayMax = 0;
	        this.startSpeedType = 0;
	        this.startSpeedConstant = 0;
	        this.startSpeedConstantMin = 0;
	        this.startSpeedConstantMax = 0;
	        this.threeDStartSize = false;
	        this.startSizeType = 0;
	        this.startSizeConstant = 0;
	        this.startSizeConstantSeparate = null;
	        this.startSizeConstantMin = 0;
	        this.startSizeConstantMax = 0;
	        this.startSizeConstantMinSeparate = null;
	        this.startSizeConstantMaxSeparate = null;
	        this.threeDStartRotation = false;
	        this.startRotationType = 0;
	        this.startRotationConstant = 0;
	        this.startRotationConstantSeparate = null;
	        this.startRotationConstantMin = 0;
	        this.startRotationConstantMax = 0;
	        this.startRotationConstantMinSeparate = null;
	        this.startRotationConstantMaxSeparate = null;
	        this.randomizeRotationDirection = 0;
	        this.startColorType = 0;
	        this.startColorConstant = null;
	        this.startColorConstantMin = null;
	        this.startColorConstantMax = null;
	        this.gravityModifier = 0;
	        this.simulationSpace = 0;
	        this.simulationSpeed = 1.0;
	        this.scaleMode = 0;
	        this.playOnAwake = false;
	        this.randomSeed = null;
	        this.autoRandomSeed = false;
	        this.isPerformanceMode = false;
	        this._firstActiveElement = 0;
	        this._firstNewElement = 0;
	        this._firstFreeElement = 0;
	        this._firstRetiredElement = 0;
	        this._owner = owner;
	        this._ownerRender = owner.particleRenderer;
	        this._boundingBoxCorners = [];
	        this._boundingSphere = new BoundSphere(new Vector3(), Number.MAX_VALUE);
	        this._boundingBox = new BoundBox(new Vector3(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE), new Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE));
	        this._currentTime = 0;
	        this._isEmitting = false;
	        this._isPlaying = false;
	        this._isPaused = false;
	        this._burstsIndex = 0;
	        this._frameRateTime = 0;
	        this._emissionTime = 0;
	        this._totalDelayTime = 0;
	        this._simulateUpdate = false;
	        this._bufferMaxParticles = 1;
	        this.duration = 5.0;
	        this.looping = true;
	        this.prewarm = false;
	        this.startDelayType = 0;
	        this.startDelay = 0.0;
	        this.startDelayMin = 0.0;
	        this.startDelayMax = 0.0;
	        this._startLifetimeType = 0;
	        this._startLifetimeConstant = 5.0;
	        this._startLifeTimeGradient = new GradientDataNumber();
	        this._startLifetimeConstantMin = 0.0;
	        this._startLifetimeConstantMax = 5.0;
	        this._startLifeTimeGradientMin = new GradientDataNumber();
	        this._startLifeTimeGradientMax = new GradientDataNumber();
	        this._maxStartLifetime = 5.0;
	        this.startSpeedType = 0;
	        this.startSpeedConstant = 5.0;
	        this.startSpeedConstantMin = 0.0;
	        this.startSpeedConstantMax = 5.0;
	        this.threeDStartSize = false;
	        this.startSizeType = 0;
	        this.startSizeConstant = 1;
	        this.startSizeConstantSeparate = new Vector3(1, 1, 1);
	        this.startSizeConstantMin = 0;
	        this.startSizeConstantMax = 1;
	        this.startSizeConstantMinSeparate = new Vector3(0, 0, 0);
	        this.startSizeConstantMaxSeparate = new Vector3(1, 1, 1);
	        this.threeDStartRotation = false;
	        this.startRotationType = 0;
	        this.startRotationConstant = 0;
	        this.startRotationConstantSeparate = new Vector3(0, 0, 0);
	        this.startRotationConstantMin = 0.0;
	        this.startRotationConstantMax = 0.0;
	        this.startRotationConstantMinSeparate = new Vector3(0, 0, 0);
	        this.startRotationConstantMaxSeparate = new Vector3(0, 0, 0);
	        this.randomizeRotationDirection = 0.0;
	        this.startColorType = 0;
	        this.startColorConstant = new Vector4(1, 1, 1, 1);
	        this.startColorConstantMin = new Vector4(1, 1, 1, 1);
	        this.startColorConstantMax = new Vector4(1, 1, 1, 1);
	        this.gravityModifier = 0.0;
	        this.simulationSpace = 1;
	        this.scaleMode = 0;
	        this.playOnAwake = true;
	        this._rand = new Rand(0);
	        this.autoRandomSeed = true;
	        this.randomSeed = new Uint32Array(1);
	        this._randomSeeds = new Uint32Array(ShurikenParticleSystem._RANDOMOFFSET.length);
	        this.isPerformanceMode = true;
	        this._emission = new Emission();
	        this._emission.enbale = true;
	    }
	    get maxParticles() {
	        return this._bufferMaxParticles - 1;
	    }
	    set maxParticles(value) {
	        var newMaxParticles = value + 1;
	        if (newMaxParticles !== this._bufferMaxParticles) {
	            this._bufferMaxParticles = newMaxParticles;
	            this._initBufferDatas();
	        }
	    }
	    get emission() {
	        return this._emission;
	    }
	    get aliveParticleCount() {
	        if (this._firstNewElement >= this._firstRetiredElement)
	            return this._firstNewElement - this._firstRetiredElement;
	        else
	            return this._bufferMaxParticles - this._firstRetiredElement + this._firstNewElement;
	    }
	    get emissionTime() {
	        return this._emissionTime > this.duration ? this.duration : this._emissionTime;
	    }
	    get shape() {
	        return this._shape;
	    }
	    set shape(value) {
	        if (this._shape !== value) {
	            if (value && value.enable)
	                this._owner._render._shaderValues.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_SHAPE);
	            else
	                this._owner._render._shaderValues.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_SHAPE);
	            this._shape = value;
	        }
	    }
	    get isAlive() {
	        if (this._isPlaying || this.aliveParticleCount > 0)
	            return true;
	        return false;
	    }
	    get isEmitting() {
	        return this._isEmitting;
	    }
	    get isPlaying() {
	        return this._isPlaying;
	    }
	    get isPaused() {
	        return this._isPaused;
	    }
	    get startLifetimeType() {
	        return this._startLifetimeType;
	    }
	    set startLifetimeType(value) {
	        var i, n;
	        switch (this.startLifetimeType) {
	            case 0:
	                this._maxStartLifetime = this.startLifetimeConstant;
	                break;
	            case 1:
	                this._maxStartLifetime = -Number.MAX_VALUE;
	                var startLifeTimeGradient = startLifeTimeGradient;
	                for (i = 0, n = startLifeTimeGradient.gradientCount; i < n; i++)
	                    this._maxStartLifetime = Math.max(this._maxStartLifetime, startLifeTimeGradient.getValueByIndex(i));
	                break;
	            case 2:
	                this._maxStartLifetime = Math.max(this.startLifetimeConstantMin, this.startLifetimeConstantMax);
	                break;
	            case 3:
	                this._maxStartLifetime = -Number.MAX_VALUE;
	                var startLifeTimeGradientMin = startLifeTimeGradientMin;
	                for (i = 0, n = startLifeTimeGradientMin.gradientCount; i < n; i++)
	                    this._maxStartLifetime = Math.max(this._maxStartLifetime, startLifeTimeGradientMin.getValueByIndex(i));
	                var startLifeTimeGradientMax = startLifeTimeGradientMax;
	                for (i = 0, n = startLifeTimeGradientMax.gradientCount; i < n; i++)
	                    this._maxStartLifetime = Math.max(this._maxStartLifetime, startLifeTimeGradientMax.getValueByIndex(i));
	                break;
	        }
	        this._startLifetimeType = value;
	    }
	    get startLifetimeConstant() {
	        return this._startLifetimeConstant;
	    }
	    set startLifetimeConstant(value) {
	        if (this._startLifetimeType === 0)
	            this._maxStartLifetime = value;
	        this._startLifetimeConstant = value;
	    }
	    get startLifeTimeGradient() {
	        return this._startLifeTimeGradient;
	    }
	    set startLifeTimeGradient(value) {
	        if (this._startLifetimeType === 1) {
	            this._maxStartLifetime = -Number.MAX_VALUE;
	            for (var i = 0, n = value.gradientCount; i < n; i++)
	                this._maxStartLifetime = Math.max(this._maxStartLifetime, value.getValueByIndex(i));
	        }
	        this._startLifeTimeGradient = value;
	    }
	    get startLifetimeConstantMin() {
	        return this._startLifetimeConstantMin;
	    }
	    set startLifetimeConstantMin(value) {
	        if (this._startLifetimeType === 2)
	            this._maxStartLifetime = Math.max(value, this._startLifetimeConstantMax);
	        this._startLifetimeConstantMin = value;
	    }
	    get startLifetimeConstantMax() {
	        return this._startLifetimeConstantMax;
	    }
	    set startLifetimeConstantMax(value) {
	        if (this._startLifetimeType === 2)
	            this._maxStartLifetime = Math.max(this._startLifetimeConstantMin, value);
	        this._startLifetimeConstantMax = value;
	    }
	    get startLifeTimeGradientMin() {
	        return this._startLifeTimeGradientMin;
	    }
	    set startLifeTimeGradientMin(value) {
	        if (this._startLifetimeType === 3) {
	            var i, n;
	            this._maxStartLifetime = -Number.MAX_VALUE;
	            for (i = 0, n = value.gradientCount; i < n; i++)
	                this._maxStartLifetime = Math.max(this._maxStartLifetime, value.getValueByIndex(i));
	            for (i = 0, n = this._startLifeTimeGradientMax.gradientCount; i < n; i++)
	                this._maxStartLifetime = Math.max(this._maxStartLifetime, this._startLifeTimeGradientMax.getValueByIndex(i));
	        }
	        this._startLifeTimeGradientMin = value;
	    }
	    get startLifeTimeGradientMax() {
	        return this._startLifeTimeGradientMax;
	    }
	    set startLifeTimeGradientMax(value) {
	        if (this._startLifetimeType === 3) {
	            var i, n;
	            this._maxStartLifetime = -Number.MAX_VALUE;
	            for (i = 0, n = this._startLifeTimeGradientMin.gradientCount; i < n; i++)
	                this._maxStartLifetime = Math.max(this._maxStartLifetime, this._startLifeTimeGradientMin.getValueByIndex(i));
	            for (i = 0, n = value.gradientCount; i < n; i++)
	                this._maxStartLifetime = Math.max(this._maxStartLifetime, value.getValueByIndex(i));
	        }
	        this._startLifeTimeGradientMax = value;
	    }
	    get velocityOverLifetime() {
	        return this._velocityOverLifetime;
	    }
	    set velocityOverLifetime(value) {
	        var shaDat = this._owner._render._shaderValues;
	        if (value) {
	            var velocity = value.velocity;
	            var velocityType = velocity.type;
	            if (value.enbale) {
	                switch (velocityType) {
	                    case 0:
	                        shaDat.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_VELOCITYOVERLIFETIMECONSTANT);
	                        break;
	                    case 1:
	                        shaDat.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_VELOCITYOVERLIFETIMECURVE);
	                        break;
	                    case 2:
	                        shaDat.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_VELOCITYOVERLIFETIMERANDOMCONSTANT);
	                        break;
	                    case 3:
	                        shaDat.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_VELOCITYOVERLIFETIMERANDOMCURVE);
	                        break;
	                }
	            }
	            else {
	                shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_VELOCITYOVERLIFETIMECONSTANT);
	                shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_VELOCITYOVERLIFETIMECURVE);
	                shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_VELOCITYOVERLIFETIMERANDOMCONSTANT);
	                shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_VELOCITYOVERLIFETIMERANDOMCURVE);
	            }
	            switch (velocityType) {
	                case 0:
	                    shaDat.setVector3(ShuriKenParticle3DShaderDeclaration.VOLVELOCITYCONST, velocity.constant);
	                    break;
	                case 1:
	                    shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.VOLVELOCITYGRADIENTX, velocity.gradientX._elements);
	                    shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.VOLVELOCITYGRADIENTY, velocity.gradientY._elements);
	                    shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.VOLVELOCITYGRADIENTZ, velocity.gradientZ._elements);
	                    break;
	                case 2:
	                    shaDat.setVector3(ShuriKenParticle3DShaderDeclaration.VOLVELOCITYCONST, velocity.constantMin);
	                    shaDat.setVector3(ShuriKenParticle3DShaderDeclaration.VOLVELOCITYCONSTMAX, velocity.constantMax);
	                    break;
	                case 3:
	                    shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.VOLVELOCITYGRADIENTX, velocity.gradientXMin._elements);
	                    shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.VOLVELOCITYGRADIENTXMAX, velocity.gradientXMax._elements);
	                    shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.VOLVELOCITYGRADIENTY, velocity.gradientYMin._elements);
	                    shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.VOLVELOCITYGRADIENTYMAX, velocity.gradientYMax._elements);
	                    shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.VOLVELOCITYGRADIENTZ, velocity.gradientZMin._elements);
	                    shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.VOLVELOCITYGRADIENTZMAX, velocity.gradientZMax._elements);
	                    break;
	            }
	            shaDat.setInt(ShuriKenParticle3DShaderDeclaration.VOLSPACETYPE, value.space);
	        }
	        else {
	            shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_VELOCITYOVERLIFETIMECONSTANT);
	            shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_VELOCITYOVERLIFETIMECURVE);
	            shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_VELOCITYOVERLIFETIMERANDOMCONSTANT);
	            shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_VELOCITYOVERLIFETIMERANDOMCURVE);
	        }
	        this._velocityOverLifetime = value;
	    }
	    get colorOverLifetime() {
	        return this._colorOverLifetime;
	    }
	    set colorOverLifetime(value) {
	        var shaDat = this._owner._render._shaderValues;
	        if (value) {
	            var color = value.color;
	            if (value.enbale) {
	                switch (color.type) {
	                    case 1:
	                        shaDat.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_COLOROVERLIFETIME);
	                        break;
	                    case 3:
	                        shaDat.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_RANDOMCOLOROVERLIFETIME);
	                        break;
	                }
	            }
	            else {
	                shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_COLOROVERLIFETIME);
	                shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_RANDOMCOLOROVERLIFETIME);
	            }
	            switch (color.type) {
	                case 1:
	                    var gradientColor = color.gradient;
	                    shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.COLOROVERLIFEGRADIENTALPHAS, gradientColor._alphaElements);
	                    shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.COLOROVERLIFEGRADIENTCOLORS, gradientColor._rgbElements);
	                    break;
	                case 3:
	                    var minGradientColor = color.gradientMin;
	                    var maxGradientColor = color.gradientMax;
	                    shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.COLOROVERLIFEGRADIENTALPHAS, minGradientColor._alphaElements);
	                    shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.COLOROVERLIFEGRADIENTCOLORS, minGradientColor._rgbElements);
	                    shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.MAXCOLOROVERLIFEGRADIENTALPHAS, maxGradientColor._alphaElements);
	                    shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.MAXCOLOROVERLIFEGRADIENTCOLORS, maxGradientColor._rgbElements);
	                    break;
	            }
	        }
	        else {
	            shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_COLOROVERLIFETIME);
	            shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_RANDOMCOLOROVERLIFETIME);
	            shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.COLOROVERLIFEGRADIENTALPHAS, gradientColor._alphaElements);
	            shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.COLOROVERLIFEGRADIENTCOLORS, gradientColor._rgbElements);
	            shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.COLOROVERLIFEGRADIENTALPHAS, minGradientColor._alphaElements);
	            shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.COLOROVERLIFEGRADIENTCOLORS, minGradientColor._rgbElements);
	            shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.MAXCOLOROVERLIFEGRADIENTALPHAS, maxGradientColor._alphaElements);
	            shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.MAXCOLOROVERLIFEGRADIENTCOLORS, maxGradientColor._rgbElements);
	        }
	        this._colorOverLifetime = value;
	    }
	    get sizeOverLifetime() {
	        return this._sizeOverLifetime;
	    }
	    set sizeOverLifetime(value) {
	        var shaDat = this._owner._render._shaderValues;
	        if (value) {
	            var size = value.size;
	            var sizeSeparate = size.separateAxes;
	            var sizeType = size.type;
	            if (value.enbale) {
	                switch (sizeType) {
	                    case 0:
	                        if (sizeSeparate)
	                            shaDat.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_SIZEOVERLIFETIMECURVESEPERATE);
	                        else
	                            shaDat.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_SIZEOVERLIFETIMECURVE);
	                        break;
	                    case 2:
	                        if (sizeSeparate)
	                            shaDat.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_SIZEOVERLIFETIMERANDOMCURVESSEPERATE);
	                        else
	                            shaDat.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_SIZEOVERLIFETIMERANDOMCURVES);
	                        break;
	                }
	            }
	            else {
	                shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_SIZEOVERLIFETIMECURVE);
	                shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_SIZEOVERLIFETIMECURVESEPERATE);
	                shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_SIZEOVERLIFETIMERANDOMCURVES);
	                shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_SIZEOVERLIFETIMERANDOMCURVESSEPERATE);
	            }
	            switch (sizeType) {
	                case 0:
	                    if (sizeSeparate) {
	                        shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.SOLSIZEGRADIENTX, size.gradientX._elements);
	                        shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.SOLSIZEGRADIENTY, size.gradientY._elements);
	                        shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.SOLSizeGradientZ, size.gradientZ._elements);
	                    }
	                    else {
	                        shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.SOLSIZEGRADIENT, size.gradient._elements);
	                    }
	                    break;
	                case 2:
	                    if (sizeSeparate) {
	                        shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.SOLSIZEGRADIENTX, size.gradientXMin._elements);
	                        shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.SOLSIZEGRADIENTXMAX, size.gradientXMax._elements);
	                        shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.SOLSIZEGRADIENTY, size.gradientYMin._elements);
	                        shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.SOLSIZEGRADIENTYMAX, size.gradientYMax._elements);
	                        shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.SOLSizeGradientZ, size.gradientZMin._elements);
	                        shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.SOLSizeGradientZMAX, size.gradientZMax._elements);
	                    }
	                    else {
	                        shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.SOLSIZEGRADIENT, size.gradientMin._elements);
	                        shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.SOLSizeGradientMax, size.gradientMax._elements);
	                    }
	                    break;
	            }
	        }
	        else {
	            shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_SIZEOVERLIFETIMECURVE);
	            shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_SIZEOVERLIFETIMECURVESEPERATE);
	            shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_SIZEOVERLIFETIMERANDOMCURVES);
	            shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_SIZEOVERLIFETIMERANDOMCURVESSEPERATE);
	        }
	        this._sizeOverLifetime = value;
	    }
	    get rotationOverLifetime() {
	        return this._rotationOverLifetime;
	    }
	    set rotationOverLifetime(value) {
	        var shaDat = this._owner._render._shaderValues;
	        if (value) {
	            var rotation = value.angularVelocity;
	            if (!rotation)
	                return;
	            var rotationSeparate = rotation.separateAxes;
	            var rotationType = rotation.type;
	            if (value.enbale) {
	                if (rotationSeparate)
	                    shaDat.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMESEPERATE);
	                else
	                    shaDat.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIME);
	                switch (rotationType) {
	                    case 0:
	                        shaDat.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMECONSTANT);
	                        break;
	                    case 1:
	                        shaDat.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMECURVE);
	                        break;
	                    case 2:
	                        shaDat.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMERANDOMCONSTANTS);
	                        break;
	                    case 3:
	                        shaDat.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMERANDOMCURVES);
	                        break;
	                }
	            }
	            else {
	                shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIME);
	                shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMESEPERATE);
	                shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMECONSTANT);
	                shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMECURVE);
	                shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMERANDOMCONSTANTS);
	                shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMERANDOMCURVES);
	            }
	            switch (rotationType) {
	                case 0:
	                    if (rotationSeparate) {
	                        shaDat.setVector3(ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYCONSTSEPRARATE, rotation.constantSeparate);
	                    }
	                    else {
	                        shaDat.setNumber(ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYCONST, rotation.constant);
	                    }
	                    break;
	                case 1:
	                    if (rotationSeparate) {
	                        shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENTX, rotation.gradientX._elements);
	                        shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENTY, rotation.gradientY._elements);
	                        shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENTZ, rotation.gradientZ._elements);
	                    }
	                    else {
	                        shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENT, rotation.gradient._elements);
	                    }
	                    break;
	                case 2:
	                    if (rotationSeparate) {
	                        shaDat.setVector3(ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYCONSTSEPRARATE, rotation.constantMinSeparate);
	                        shaDat.setVector3(ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYCONSTMAXSEPRARATE, rotation.constantMaxSeparate);
	                    }
	                    else {
	                        shaDat.setNumber(ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYCONST, rotation.constantMin);
	                        shaDat.setNumber(ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYCONSTMAX, rotation.constantMax);
	                    }
	                    break;
	                case 3:
	                    if (rotationSeparate) {
	                        shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENTX, rotation.gradientXMin._elements);
	                        shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENTXMAX, rotation.gradientXMax._elements);
	                        shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENTY, rotation.gradientYMin._elements);
	                        shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENTYMAX, rotation.gradientYMax._elements);
	                        shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENTZ, rotation.gradientZMin._elements);
	                        shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENTZMAX, rotation.gradientZMax._elements);
	                    }
	                    else {
	                        shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENT, rotation.gradientMin._elements);
	                        shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENTMAX, rotation.gradientMax._elements);
	                    }
	                    break;
	            }
	        }
	        else {
	            shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIME);
	            shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMESEPERATE);
	            shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMECONSTANT);
	            shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMECURVE);
	            shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMERANDOMCONSTANTS);
	            shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMERANDOMCURVES);
	        }
	        this._rotationOverLifetime = value;
	    }
	    get textureSheetAnimation() {
	        return this._textureSheetAnimation;
	    }
	    set textureSheetAnimation(value) {
	        var shaDat = this._owner._render._shaderValues;
	        if (value) {
	            var frameOverTime = value.frame;
	            var textureAniType = frameOverTime.type;
	            if (value.enable) {
	                switch (textureAniType) {
	                    case 1:
	                        shaDat.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_TEXTURESHEETANIMATIONCURVE);
	                        break;
	                    case 3:
	                        shaDat.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_TEXTURESHEETANIMATIONRANDOMCURVE);
	                        break;
	                }
	            }
	            else {
	                shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_TEXTURESHEETANIMATIONCURVE);
	                shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_TEXTURESHEETANIMATIONRANDOMCURVE);
	            }
	            if (textureAniType === 1 || textureAniType === 3) {
	                shaDat.setNumber(ShuriKenParticle3DShaderDeclaration.TEXTURESHEETANIMATIONCYCLES, value.cycles);
	                var title = value.tiles;
	                var _uvLengthE = this._uvLength;
	                _uvLengthE.x = 1.0 / title.x;
	                _uvLengthE.y = 1.0 / title.y;
	                shaDat.setVector2(ShuriKenParticle3DShaderDeclaration.TEXTURESHEETANIMATIONSUBUVLENGTH, this._uvLength);
	            }
	            switch (textureAniType) {
	                case 1:
	                    shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.TEXTURESHEETANIMATIONGRADIENTUVS, frameOverTime.frameOverTimeData._elements);
	                    break;
	                case 3:
	                    shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.TEXTURESHEETANIMATIONGRADIENTUVS, frameOverTime.frameOverTimeDataMin._elements);
	                    shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.TEXTURESHEETANIMATIONGRADIENTMAXUVS, frameOverTime.frameOverTimeDataMax._elements);
	                    break;
	            }
	        }
	        else {
	            shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_TEXTURESHEETANIMATIONCURVE);
	            shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_TEXTURESHEETANIMATIONRANDOMCURVE);
	        }
	        this._textureSheetAnimation = value;
	    }
	    _getVertexBuffer(index = 0) {
	        if (index === 0)
	            return this._vertexBuffer;
	        else
	            return null;
	    }
	    _getIndexBuffer() {
	        return this._indexBuffer;
	    }
	    _generateBoundingSphere() {
	        var centerE = this._boundingSphere.center;
	        centerE.x = 0;
	        centerE.y = 0;
	        centerE.z = 0;
	        this._boundingSphere.radius = Number.MAX_VALUE;
	    }
	    _generateBoundingBox() {
	        var particle = this._owner;
	        var particleRender = particle.particleRenderer;
	        var boundMin = this._boundingBox.min;
	        var boundMax = this._boundingBox.max;
	        var i, n;
	        var maxStartLifeTime;
	        switch (this.startLifetimeType) {
	            case 0:
	                maxStartLifeTime = this.startLifetimeConstant;
	                break;
	            case 1:
	                maxStartLifeTime = -Number.MAX_VALUE;
	                var startLifeTimeGradient = startLifeTimeGradient;
	                for (i = 0, n = startLifeTimeGradient.gradientCount; i < n; i++)
	                    maxStartLifeTime = Math.max(maxStartLifeTime, startLifeTimeGradient.getValueByIndex(i));
	                break;
	            case 2:
	                maxStartLifeTime = Math.max(this.startLifetimeConstantMin, this.startLifetimeConstantMax);
	                break;
	            case 3:
	                maxStartLifeTime = -Number.MAX_VALUE;
	                var startLifeTimeGradientMin = startLifeTimeGradientMin;
	                for (i = 0, n = startLifeTimeGradientMin.gradientCount; i < n; i++)
	                    maxStartLifeTime = Math.max(maxStartLifeTime, startLifeTimeGradientMin.getValueByIndex(i));
	                var startLifeTimeGradientMax = startLifeTimeGradientMax;
	                for (i = 0, n = startLifeTimeGradientMax.gradientCount; i < n; i++)
	                    maxStartLifeTime = Math.max(maxStartLifeTime, startLifeTimeGradientMax.getValueByIndex(i));
	                break;
	        }
	        var minStartSpeed, maxStartSpeed;
	        switch (this.startSpeedType) {
	            case 0:
	                minStartSpeed = maxStartSpeed = this.startSpeedConstant;
	                break;
	            case 1:
	                break;
	            case 2:
	                minStartSpeed = this.startLifetimeConstantMin;
	                maxStartSpeed = this.startLifetimeConstantMax;
	                break;
	            case 3:
	                break;
	        }
	        var minPosition, maxPosition, minDirection, maxDirection;
	        if (this._shape && this._shape.enable) ;
	        else {
	            minPosition = maxPosition = Vector3._ZERO;
	            minDirection = Vector3._ZERO;
	            maxDirection = Vector3._UnitZ;
	        }
	        var startMinVelocity = new Vector3(minDirection.x * minStartSpeed, minDirection.y * minStartSpeed, minDirection.z * minStartSpeed);
	        var startMaxVelocity = new Vector3(maxDirection.x * maxStartSpeed, maxDirection.y * maxStartSpeed, maxDirection.z * maxStartSpeed);
	        if (this._velocityOverLifetime && this._velocityOverLifetime.enbale) {
	            var lifeMinVelocity;
	            var lifeMaxVelocity;
	            var velocity = this._velocityOverLifetime.velocity;
	            switch (velocity.type) {
	                case 0:
	                    lifeMinVelocity = lifeMaxVelocity = velocity.constant;
	                    break;
	                case 1:
	                    lifeMinVelocity = lifeMaxVelocity = new Vector3(velocity.gradientX.getAverageValue(), velocity.gradientY.getAverageValue(), velocity.gradientZ.getAverageValue());
	                    break;
	                case 2:
	                    lifeMinVelocity = velocity.constantMin;
	                    lifeMaxVelocity = velocity.constantMax;
	                    break;
	                case 3:
	                    lifeMinVelocity = new Vector3(velocity.gradientXMin.getAverageValue(), velocity.gradientYMin.getAverageValue(), velocity.gradientZMin.getAverageValue());
	                    lifeMaxVelocity = new Vector3(velocity.gradientXMax.getAverageValue(), velocity.gradientYMax.getAverageValue(), velocity.gradientZMax.getAverageValue());
	                    break;
	            }
	        }
	        var positionScale, velocityScale;
	        var transform = this._owner.transform;
	        var worldPosition = transform.position;
	        var sizeScale = ShurikenParticleSystem._tempVector39;
	        var renderMode = particleRender.renderMode;
	        switch (this.scaleMode) {
	            case 0:
	                var scale = transform.getWorldLossyScale();
	                positionScale = scale;
	                sizeScale.x = scale.x;
	                sizeScale.y = scale.z;
	                sizeScale.z = scale.y;
	                (renderMode === 1) && (velocityScale = scale);
	                break;
	            case 1:
	                var localScale = transform.localScale;
	                positionScale = localScale;
	                sizeScale.x = localScale.x;
	                sizeScale.y = localScale.z;
	                sizeScale.z = localScale.y;
	                (renderMode === 1) && (velocityScale = localScale);
	                break;
	            case 2:
	                positionScale = transform.getWorldLossyScale();
	                sizeScale.x = sizeScale.y = sizeScale.z = 1;
	                (renderMode === 1) && (velocityScale = Vector3._ONE);
	                break;
	        }
	        var minStratPosition, maxStratPosition;
	        if (this._velocityOverLifetime && this._velocityOverLifetime.enbale) ;
	        else {
	            minStratPosition = new Vector3(startMinVelocity.x * maxStartLifeTime, startMinVelocity.y * maxStartLifeTime, startMinVelocity.z * maxStartLifeTime);
	            maxStratPosition = new Vector3(startMaxVelocity.x * maxStartLifeTime, startMaxVelocity.y * maxStartLifeTime, startMaxVelocity.z * maxStartLifeTime);
	            if (this.scaleMode != 2) {
	                Vector3.add(minPosition, minStratPosition, boundMin);
	                Vector3.multiply(positionScale, boundMin, boundMin);
	                Vector3.add(maxPosition, maxStratPosition, boundMax);
	                Vector3.multiply(positionScale, boundMax, boundMax);
	            }
	            else {
	                Vector3.multiply(positionScale, minPosition, boundMin);
	                Vector3.add(boundMin, minStratPosition, boundMin);
	                Vector3.multiply(positionScale, maxPosition, boundMax);
	                Vector3.add(boundMax, maxStratPosition, boundMax);
	            }
	        }
	        switch (this.simulationSpace) {
	            case 0:
	                break;
	            case 1:
	                Vector3.add(boundMin, worldPosition, boundMin);
	                Vector3.add(boundMax, worldPosition, boundMax);
	                break;
	        }
	        var maxSize, maxSizeY;
	        switch (this.startSizeType) {
	            case 0:
	                if (this.threeDStartSize) {
	                    var startSizeConstantSeparate = startSizeConstantSeparate;
	                    maxSize = Math.max(startSizeConstantSeparate.x, startSizeConstantSeparate.y);
	                    if (renderMode === 1)
	                        maxSizeY = startSizeConstantSeparate.y;
	                }
	                else {
	                    maxSize = this.startSizeConstant;
	                    if (renderMode === 1)
	                        maxSizeY = this.startSizeConstant;
	                }
	                break;
	            case 1:
	                break;
	            case 2:
	                if (this.threeDStartSize) {
	                    var startSizeConstantMaxSeparate = startSizeConstantMaxSeparate;
	                    maxSize = Math.max(startSizeConstantMaxSeparate.x, startSizeConstantMaxSeparate.y);
	                    if (renderMode === 1)
	                        maxSizeY = startSizeConstantMaxSeparate.y;
	                }
	                else {
	                    maxSize = this.startSizeConstantMax;
	                    if (renderMode === 1)
	                        maxSizeY = this.startSizeConstantMax;
	                }
	                break;
	            case 3:
	                break;
	        }
	        if (this._sizeOverLifetime && this._sizeOverLifetime.enbale) {
	            var size = this._sizeOverLifetime.size;
	            maxSize *= this._sizeOverLifetime.size.getMaxSizeInGradient();
	        }
	        var threeDMaxSize = ShurikenParticleSystem._tempVector30;
	        var rotSize, nonRotSize;
	        switch (renderMode) {
	            case 0:
	                rotSize = maxSize * ShurikenParticleSystem.halfKSqrtOf2;
	                Vector3.scale(sizeScale, maxSize, threeDMaxSize);
	                Vector3.subtract(boundMin, threeDMaxSize, boundMin);
	                Vector3.add(boundMax, threeDMaxSize, boundMax);
	                break;
	            case 1:
	                var maxStretchPosition = ShurikenParticleSystem._tempVector31;
	                var maxStretchVelocity = ShurikenParticleSystem._tempVector32;
	                var minStretchVelocity = ShurikenParticleSystem._tempVector33;
	                var minStretchPosition = ShurikenParticleSystem._tempVector34;
	                if (this._velocityOverLifetime && this._velocityOverLifetime.enbale) ;
	                else {
	                    Vector3.multiply(velocityScale, startMaxVelocity, maxStretchVelocity);
	                    Vector3.multiply(velocityScale, startMinVelocity, minStretchVelocity);
	                }
	                var sizeStretch = maxSizeY * particleRender.stretchedBillboardLengthScale;
	                var maxStretchLength = Vector3.scalarLength(maxStretchVelocity) * particleRender.stretchedBillboardSpeedScale + sizeStretch;
	                var minStretchLength = Vector3.scalarLength(minStretchVelocity) * particleRender.stretchedBillboardSpeedScale + sizeStretch;
	                var norMaxStretchVelocity = ShurikenParticleSystem._tempVector35;
	                var norMinStretchVelocity = ShurikenParticleSystem._tempVector36;
	                Vector3.normalize(maxStretchVelocity, norMaxStretchVelocity);
	                Vector3.scale(norMaxStretchVelocity, maxStretchLength, minStretchPosition);
	                Vector3.subtract(maxStratPosition, minStretchPosition, minStretchPosition);
	                Vector3.normalize(minStretchVelocity, norMinStretchVelocity);
	                Vector3.scale(norMinStretchVelocity, minStretchLength, maxStretchPosition);
	                Vector3.add(minStratPosition, maxStretchPosition, maxStretchPosition);
	                rotSize = maxSize * ShurikenParticleSystem.halfKSqrtOf2;
	                Vector3.scale(sizeScale, rotSize, threeDMaxSize);
	                var halfNorMaxStretchVelocity = ShurikenParticleSystem._tempVector37;
	                var halfNorMinStretchVelocity = ShurikenParticleSystem._tempVector38;
	                Vector3.scale(norMaxStretchVelocity, 0.5, halfNorMaxStretchVelocity);
	                Vector3.scale(norMinStretchVelocity, 0.5, halfNorMinStretchVelocity);
	                Vector3.multiply(halfNorMaxStretchVelocity, sizeScale, halfNorMaxStretchVelocity);
	                Vector3.multiply(halfNorMinStretchVelocity, sizeScale, halfNorMinStretchVelocity);
	                Vector3.add(boundMin, halfNorMinStretchVelocity, boundMin);
	                Vector3.min(boundMin, minStretchPosition, boundMin);
	                Vector3.subtract(boundMin, threeDMaxSize, boundMin);
	                Vector3.subtract(boundMax, halfNorMaxStretchVelocity, boundMax);
	                Vector3.max(boundMax, maxStretchPosition, boundMax);
	                Vector3.add(boundMax, threeDMaxSize, boundMax);
	                break;
	            case 2:
	                maxSize *= Math.cos(0.78539816339744830961566084581988);
	                nonRotSize = maxSize * 0.5;
	                threeDMaxSize.x = sizeScale.x * nonRotSize;
	                threeDMaxSize.y = sizeScale.z * nonRotSize;
	                Vector3.subtract(boundMin, threeDMaxSize, boundMin);
	                Vector3.add(boundMax, threeDMaxSize, boundMax);
	                break;
	            case 3:
	                maxSize *= Math.cos(0.78539816339744830961566084581988);
	                nonRotSize = maxSize * 0.5;
	                Vector3.scale(sizeScale, nonRotSize, threeDMaxSize);
	                Vector3.subtract(boundMin, threeDMaxSize, boundMin);
	                Vector3.add(boundMax, threeDMaxSize, boundMax);
	                break;
	        }
	        this._boundingBox.getCorners(this._boundingBoxCorners);
	    }
	    _updateEmission() {
	        if (!this.isAlive)
	            return;
	        if (this._simulateUpdate) {
	            this._simulateUpdate = false;
	        }
	        else {
	            var elapsedTime = (this._startUpdateLoopCount !== Laya.Stat.loopCount && !this._isPaused) ? this._owner._scene.timer._delta / 1000.0 : 0;
	            elapsedTime = Math.min(ShurikenParticleSystem._maxElapsedTime, elapsedTime * this.simulationSpeed);
	            this._updateParticles(elapsedTime);
	        }
	    }
	    _updateParticles(elapsedTime) {
	        if (this._ownerRender.renderMode === 4 && !this._ownerRender.mesh)
	            return;
	        this._currentTime += elapsedTime;
	        this._retireActiveParticles();
	        this._freeRetiredParticles();
	        this._totalDelayTime += elapsedTime;
	        if (this._totalDelayTime < this._playStartDelay) {
	            return;
	        }
	        if (this._emission.enbale && this._isEmitting && !this._isPaused)
	            this._advanceTime(elapsedTime, this._currentTime);
	    }
	    _updateParticlesSimulationRestart(time) {
	        this._firstActiveElement = 0;
	        this._firstNewElement = 0;
	        this._firstFreeElement = 0;
	        this._firstRetiredElement = 0;
	        this._burstsIndex = 0;
	        this._frameRateTime = time;
	        this._emissionTime = 0;
	        this._totalDelayTime = 0;
	        this._currentTime = time;
	        var delayTime = time;
	        if (delayTime < this._playStartDelay) {
	            this._totalDelayTime = delayTime;
	            return;
	        }
	        if (this._emission.enbale)
	            this._advanceTime(time, time);
	    }
	    _retireActiveParticles() {
	        const epsilon = 0.0001;
	        while (this._firstActiveElement != this._firstNewElement) {
	            var index = this._firstActiveElement * this._floatCountPerVertex * this._vertexStride;
	            var timeIndex = index + this._timeIndex;
	            var particleAge = this._currentTime - this._vertices[timeIndex];
	            if (particleAge + epsilon < this._vertices[index + this._startLifeTimeIndex])
	                break;
	            this._vertices[timeIndex] = this._drawCounter;
	            this._firstActiveElement++;
	            if (this._firstActiveElement >= this._bufferMaxParticles)
	                this._firstActiveElement = 0;
	        }
	    }
	    _freeRetiredParticles() {
	        while (this._firstRetiredElement != this._firstActiveElement) {
	            var age = this._drawCounter - this._vertices[this._firstRetiredElement * this._floatCountPerVertex * this._vertexStride + this._timeIndex];
	            if (this.isPerformanceMode)
	                if (age < 3)
	                    break;
	            this._firstRetiredElement++;
	            if (this._firstRetiredElement >= this._bufferMaxParticles)
	                this._firstRetiredElement = 0;
	        }
	    }
	    _burst(fromTime, toTime) {
	        var totalEmitCount = 0;
	        var bursts = this._emission._bursts;
	        for (var n = bursts.length; this._burstsIndex < n; this._burstsIndex++) {
	            var burst = bursts[this._burstsIndex];
	            var burstTime = burst.time;
	            if (fromTime <= burstTime && burstTime < toTime) {
	                var emitCount;
	                if (this.autoRandomSeed) {
	                    emitCount = Laya.MathUtil.lerp(burst.minCount, burst.maxCount, Math.random());
	                }
	                else {
	                    this._rand.seed = this._randomSeeds[0];
	                    emitCount = Laya.MathUtil.lerp(burst.minCount, burst.maxCount, this._rand.getFloat());
	                    this._randomSeeds[0] = this._rand.seed;
	                }
	                totalEmitCount += emitCount;
	            }
	            else {
	                break;
	            }
	        }
	        return totalEmitCount;
	    }
	    _advanceTime(elapsedTime, emitTime) {
	        var i;
	        var lastEmissionTime = this._emissionTime;
	        this._emissionTime += elapsedTime;
	        var totalEmitCount = 0;
	        if (this._emissionTime > this.duration) {
	            if (this.looping) {
	                totalEmitCount += this._burst(lastEmissionTime, this._emissionTime);
	                this._emissionTime -= this.duration;
	                this._burstsIndex = 0;
	                totalEmitCount += this._burst(0, this._emissionTime);
	            }
	            else {
	                totalEmitCount = Math.min(this.maxParticles - this.aliveParticleCount, totalEmitCount);
	                for (i = 0; i < totalEmitCount; i++)
	                    this.emit(emitTime);
	                this._isPlaying = false;
	                this.stop();
	                return;
	            }
	        }
	        else {
	            totalEmitCount += this._burst(lastEmissionTime, this._emissionTime);
	        }
	        totalEmitCount = Math.min(this.maxParticles - this.aliveParticleCount, totalEmitCount);
	        for (i = 0; i < totalEmitCount; i++)
	            this.emit(emitTime);
	        var emissionRate = this.emission.emissionRate;
	        if (emissionRate > 0) {
	            var minEmissionTime = 1 / emissionRate;
	            this._frameRateTime += minEmissionTime;
	            this._frameRateTime = this._currentTime - (this._currentTime - this._frameRateTime) % this._maxStartLifetime;
	            while (this._frameRateTime <= emitTime) {
	                if (this.emit(this._frameRateTime))
	                    this._frameRateTime += minEmissionTime;
	                else
	                    break;
	            }
	            this._frameRateTime = Math.floor(emitTime / minEmissionTime) * minEmissionTime;
	        }
	    }
	    _initBufferDatas() {
	        if (this._vertexBuffer) {
	            this._vertexBuffer.destroy();
	            this._indexBuffer.destroy();
	        }
	        var gl = Laya.LayaGL.instance;
	        var render = this._ownerRender;
	        var renderMode = render.renderMode;
	        if (renderMode !== -1 && this.maxParticles > 0) {
	            var indices, i, j, m, indexOffset, perPartOffset, vertexDeclaration;
	            var vbMemorySize = 0, memorySize = 0;
	            var mesh = render.mesh;
	            if (renderMode === 4) {
	                if (mesh) {
	                    vertexDeclaration = VertexShurikenParticleMesh.vertexDeclaration;
	                    this._floatCountPerVertex = vertexDeclaration.vertexStride / 4;
	                    this._startLifeTimeIndex = 12;
	                    this._timeIndex = 16;
	                    this._vertexStride = mesh._vertexCount;
	                    var totalVertexCount = this._bufferMaxParticles * this._vertexStride;
	                    var vbCount = Math.floor(totalVertexCount / 65535) + 1;
	                    var lastVBVertexCount = totalVertexCount % 65535;
	                    if (vbCount > 1) {
	                        throw new Error("ShurikenParticleSystem:the maxParticleCount multiply mesh vertexCount is large than 65535.");
	                    }
	                    vbMemorySize = vertexDeclaration.vertexStride * lastVBVertexCount;
	                    this._vertexBuffer = new VertexBuffer3D(vbMemorySize, gl.DYNAMIC_DRAW);
	                    this._vertexBuffer.vertexDeclaration = vertexDeclaration;
	                    this._vertices = new Float32Array(this._floatCountPerVertex * lastVBVertexCount);
	                    this._indexStride = mesh._indexBuffer.indexCount;
	                    var indexDatas = mesh._indexBuffer.getData();
	                    var indexCount = this._bufferMaxParticles * this._indexStride;
	                    this._indexBuffer = new IndexBuffer3D(IndexBuffer3D.INDEXTYPE_USHORT, indexCount, gl.STATIC_DRAW);
	                    indices = new Uint16Array(indexCount);
	                    memorySize = vbMemorySize + indexCount * 2;
	                    indexOffset = 0;
	                    for (i = 0; i < this._bufferMaxParticles; i++) {
	                        var indexValueOffset = i * this._vertexStride;
	                        for (j = 0, m = indexDatas.length; j < m; j++)
	                            indices[indexOffset++] = indexValueOffset + indexDatas[j];
	                    }
	                    this._indexBuffer.setData(indices);
	                    this._bufferState.bind();
	                    this._bufferState.applyVertexBuffer(this._vertexBuffer);
	                    this._bufferState.applyIndexBuffer(this._indexBuffer);
	                    this._bufferState.unBind();
	                }
	            }
	            else {
	                vertexDeclaration = VertexShurikenParticleBillboard.vertexDeclaration;
	                this._floatCountPerVertex = vertexDeclaration.vertexStride / 4;
	                this._startLifeTimeIndex = 7;
	                this._timeIndex = 11;
	                this._vertexStride = 4;
	                vbMemorySize = vertexDeclaration.vertexStride * this._bufferMaxParticles * this._vertexStride;
	                this._vertexBuffer = new VertexBuffer3D(vbMemorySize, gl.DYNAMIC_DRAW);
	                this._vertexBuffer.vertexDeclaration = vertexDeclaration;
	                this._vertices = new Float32Array(this._floatCountPerVertex * this._bufferMaxParticles * this._vertexStride);
	                for (i = 0; i < this._bufferMaxParticles; i++) {
	                    perPartOffset = i * this._floatCountPerVertex * this._vertexStride;
	                    this._vertices[perPartOffset] = -0.5;
	                    this._vertices[perPartOffset + 1] = -0.5;
	                    this._vertices[perPartOffset + 2] = 0;
	                    this._vertices[perPartOffset + 3] = 1;
	                    perPartOffset += this._floatCountPerVertex;
	                    this._vertices[perPartOffset] = 0.5;
	                    this._vertices[perPartOffset + 1] = -0.5;
	                    this._vertices[perPartOffset + 2] = 1;
	                    this._vertices[perPartOffset + 3] = 1;
	                    perPartOffset += this._floatCountPerVertex;
	                    this._vertices[perPartOffset] = 0.5;
	                    this._vertices[perPartOffset + 1] = 0.5;
	                    this._vertices[perPartOffset + 2] = 1;
	                    this._vertices[perPartOffset + 3] = 0;
	                    perPartOffset += this._floatCountPerVertex;
	                    this._vertices[perPartOffset] = -0.5;
	                    this._vertices[perPartOffset + 1] = 0.5;
	                    this._vertices[perPartOffset + 2] = 0;
	                    this._vertices[perPartOffset + 3] = 0;
	                }
	                this._indexStride = 6;
	                this._indexBuffer = new IndexBuffer3D(IndexBuffer3D.INDEXTYPE_USHORT, this._bufferMaxParticles * 6, gl.STATIC_DRAW);
	                indices = new Uint16Array(this._bufferMaxParticles * 6);
	                for (i = 0; i < this._bufferMaxParticles; i++) {
	                    indexOffset = i * 6;
	                    var firstVertex = i * this._vertexStride, secondVertex = firstVertex + 2;
	                    indices[indexOffset++] = firstVertex;
	                    indices[indexOffset++] = secondVertex;
	                    indices[indexOffset++] = firstVertex + 1;
	                    indices[indexOffset++] = firstVertex;
	                    indices[indexOffset++] = firstVertex + 3;
	                    indices[indexOffset++] = secondVertex;
	                }
	                this._indexBuffer.setData(indices);
	                memorySize = vbMemorySize + this._bufferMaxParticles * 6 * 2;
	                this._bufferState.bind();
	                this._bufferState.applyVertexBuffer(this._vertexBuffer);
	                this._bufferState.applyIndexBuffer(this._indexBuffer);
	                this._bufferState.unBind();
	            }
	            Laya.Resource._addMemory(memorySize, memorySize);
	        }
	    }
	    destroy() {
	        super.destroy();
	        var memorySize = this._vertexBuffer._byteLength + this._indexBuffer.indexCount * 2;
	        Laya.Resource._addMemory(-memorySize, -memorySize);
	        this._bufferState.destroy();
	        this._vertexBuffer.destroy();
	        this._indexBuffer.destroy();
	        this._emission.destroy();
	        this._bufferState = null;
	        this._vertexBuffer = null;
	        this._indexBuffer = null;
	        this._owner = null;
	        this._vertices = null;
	        this._indexBuffer = null;
	        this._emission = null;
	        this._shape = null;
	        this.startLifeTimeGradient = null;
	        this.startLifeTimeGradientMin = null;
	        this.startLifeTimeGradientMax = null;
	        this.startSizeConstantSeparate = null;
	        this.startSizeConstantMinSeparate = null;
	        this.startSizeConstantMaxSeparate = null;
	        this.startRotationConstantSeparate = null;
	        this.startRotationConstantMinSeparate = null;
	        this.startRotationConstantMaxSeparate = null;
	        this.startColorConstant = null;
	        this.startColorConstantMin = null;
	        this.startColorConstantMax = null;
	        this._velocityOverLifetime = null;
	        this._colorOverLifetime = null;
	        this._sizeOverLifetime = null;
	        this._rotationOverLifetime = null;
	        this._textureSheetAnimation = null;
	    }
	    emit(time) {
	        var position = ShurikenParticleSystem._tempPosition;
	        var direction = ShurikenParticleSystem._tempDirection;
	        if (this._shape && this._shape.enable) {
	            if (this.autoRandomSeed)
	                this._shape.generatePositionAndDirection(position, direction);
	            else
	                this._shape.generatePositionAndDirection(position, direction, this._rand, this._randomSeeds);
	        }
	        else {
	            position.x = position.y = position.z = 0;
	            direction.x = direction.y = 0;
	            direction.z = 1;
	        }
	        return this.addParticle(position, direction, time);
	    }
	    addParticle(position, direction, time) {
	        Vector3.normalize(direction, direction);
	        var nextFreeParticle = this._firstFreeElement + 1;
	        if (nextFreeParticle >= this._bufferMaxParticles)
	            nextFreeParticle = 0;
	        if (nextFreeParticle === this._firstRetiredElement)
	            return false;
	        var transform = this._owner.transform;
	        ShurikenParticleData.create(this, this._ownerRender, transform);
	        var particleAge = this._currentTime - time;
	        if (particleAge >= ShurikenParticleData.startLifeTime)
	            return true;
	        var pos, rot;
	        if (this.simulationSpace == 0) {
	            pos = transform.position;
	            rot = transform.rotation;
	        }
	        var startSpeed;
	        switch (this.startSpeedType) {
	            case 0:
	                startSpeed = this.startSpeedConstant;
	                break;
	            case 2:
	                if (this.autoRandomSeed) {
	                    startSpeed = Laya.MathUtil.lerp(this.startSpeedConstantMin, this.startSpeedConstantMax, Math.random());
	                }
	                else {
	                    this._rand.seed = this._randomSeeds[8];
	                    startSpeed = Laya.MathUtil.lerp(this.startSpeedConstantMin, this.startSpeedConstantMax, this._rand.getFloat());
	                    this._randomSeeds[8] = this._rand.seed;
	                }
	                break;
	        }
	        var randomVelocityX, randomVelocityY, randomVelocityZ, randomColor, randomSize, randomRotation, randomTextureAnimation;
	        var needRandomVelocity = this._velocityOverLifetime && this._velocityOverLifetime.enbale;
	        if (needRandomVelocity) {
	            var velocityType = this._velocityOverLifetime.velocity.type;
	            if (velocityType === 2 || velocityType === 3) {
	                if (this.autoRandomSeed) {
	                    randomVelocityX = Math.random();
	                    randomVelocityY = Math.random();
	                    randomVelocityZ = Math.random();
	                }
	                else {
	                    this._rand.seed = this._randomSeeds[9];
	                    randomVelocityX = this._rand.getFloat();
	                    randomVelocityY = this._rand.getFloat();
	                    randomVelocityZ = this._rand.getFloat();
	                    this._randomSeeds[9] = this._rand.seed;
	                }
	            }
	            else {
	                needRandomVelocity = false;
	            }
	        }
	        else {
	            needRandomVelocity = false;
	        }
	        var needRandomColor = this._colorOverLifetime && this._colorOverLifetime.enbale;
	        if (needRandomColor) {
	            var colorType = this._colorOverLifetime.color.type;
	            if (colorType === 3) {
	                if (this.autoRandomSeed) {
	                    randomColor = Math.random();
	                }
	                else {
	                    this._rand.seed = this._randomSeeds[10];
	                    randomColor = this._rand.getFloat();
	                    this._randomSeeds[10] = this._rand.seed;
	                }
	            }
	            else {
	                needRandomColor = false;
	            }
	        }
	        else {
	            needRandomColor = false;
	        }
	        var needRandomSize = this._sizeOverLifetime && this._sizeOverLifetime.enbale;
	        if (needRandomSize) {
	            var sizeType = this._sizeOverLifetime.size.type;
	            if (sizeType === 3) {
	                if (this.autoRandomSeed) {
	                    randomSize = Math.random();
	                }
	                else {
	                    this._rand.seed = this._randomSeeds[11];
	                    randomSize = this._rand.getFloat();
	                    this._randomSeeds[11] = this._rand.seed;
	                }
	            }
	            else {
	                needRandomSize = false;
	            }
	        }
	        else {
	            needRandomSize = false;
	        }
	        var needRandomRotation = this._rotationOverLifetime && this._rotationOverLifetime.enbale;
	        if (needRandomRotation) {
	            var rotationType = this._rotationOverLifetime.angularVelocity.type;
	            if (rotationType === 2 || rotationType === 3) {
	                if (this.autoRandomSeed) {
	                    randomRotation = Math.random();
	                }
	                else {
	                    this._rand.seed = this._randomSeeds[12];
	                    randomRotation = this._rand.getFloat();
	                    this._randomSeeds[12] = this._rand.seed;
	                }
	            }
	            else {
	                needRandomRotation = false;
	            }
	        }
	        else {
	            needRandomRotation = false;
	        }
	        var needRandomTextureAnimation = this._textureSheetAnimation && this._textureSheetAnimation.enable;
	        if (needRandomTextureAnimation) {
	            var textureAnimationType = this._textureSheetAnimation.frame.type;
	            if (textureAnimationType === 3) {
	                if (this.autoRandomSeed) {
	                    randomTextureAnimation = Math.random();
	                }
	                else {
	                    this._rand.seed = this._randomSeeds[15];
	                    randomTextureAnimation = this._rand.getFloat();
	                    this._randomSeeds[15] = this._rand.seed;
	                }
	            }
	            else {
	                needRandomTextureAnimation = false;
	            }
	        }
	        else {
	            needRandomTextureAnimation = false;
	        }
	        var startIndex = this._firstFreeElement * this._floatCountPerVertex * this._vertexStride;
	        var subU = ShurikenParticleData.startUVInfo[0];
	        var subV = ShurikenParticleData.startUVInfo[1];
	        var startU = ShurikenParticleData.startUVInfo[2];
	        var startV = ShurikenParticleData.startUVInfo[3];
	        var meshVertices, meshVertexStride, meshPosOffset, meshCorOffset, meshUVOffset, meshVertexIndex;
	        var render = this._ownerRender;
	        if (render.renderMode === 4) {
	            var meshVB = render.mesh._vertexBuffer;
	            meshVertices = meshVB.getFloat32Data();
	            var meshVertexDeclaration = meshVB.vertexDeclaration;
	            meshPosOffset = meshVertexDeclaration.getVertexElementByUsage(VertexMesh.MESH_POSITION0)._offset / 4;
	            var colorElement = meshVertexDeclaration.getVertexElementByUsage(VertexMesh.MESH_COLOR0);
	            meshCorOffset = colorElement ? colorElement._offset / 4 : -1;
	            var uvElement = meshVertexDeclaration.getVertexElementByUsage(VertexMesh.MESH_TEXTURECOORDINATE0);
	            meshUVOffset = uvElement ? uvElement._offset / 4 : -1;
	            meshVertexStride = meshVertexDeclaration.vertexStride / 4;
	            meshVertexIndex = 0;
	        }
	        else {
	            this._vertices[startIndex + 2] = startU;
	            this._vertices[startIndex + 3] = startV + subV;
	            var secondOffset = startIndex + this._floatCountPerVertex;
	            this._vertices[secondOffset + 2] = startU + subU;
	            this._vertices[secondOffset + 3] = startV + subV;
	            var thirdOffset = secondOffset + this._floatCountPerVertex;
	            this._vertices[thirdOffset + 2] = startU + subU;
	            this._vertices[thirdOffset + 3] = startV;
	            var fourthOffset = thirdOffset + this._floatCountPerVertex;
	            this._vertices[fourthOffset + 2] = startU;
	            this._vertices[fourthOffset + 3] = startV;
	        }
	        for (var i = startIndex, n = startIndex + this._floatCountPerVertex * this._vertexStride; i < n; i += this._floatCountPerVertex) {
	            var offset;
	            if (render.renderMode === 4) {
	                offset = i;
	                var vertexOffset = meshVertexStride * (meshVertexIndex++);
	                var meshOffset = vertexOffset + meshPosOffset;
	                this._vertices[offset++] = meshVertices[meshOffset++];
	                this._vertices[offset++] = meshVertices[meshOffset++];
	                this._vertices[offset++] = meshVertices[meshOffset];
	                if (meshCorOffset === -1) {
	                    this._vertices[offset++] = 1.0;
	                    this._vertices[offset++] = 1.0;
	                    this._vertices[offset++] = 1.0;
	                    this._vertices[offset++] = 1.0;
	                }
	                else {
	                    meshOffset = vertexOffset + meshCorOffset;
	                    this._vertices[offset++] = meshVertices[meshOffset++];
	                    this._vertices[offset++] = meshVertices[meshOffset++];
	                    this._vertices[offset++] = meshVertices[meshOffset++];
	                    this._vertices[offset++] = meshVertices[meshOffset];
	                }
	                if (meshUVOffset === -1) {
	                    this._vertices[offset++] = 0.0;
	                    this._vertices[offset++] = 0.0;
	                }
	                else {
	                    meshOffset = vertexOffset + meshUVOffset;
	                    this._vertices[offset++] = startU + meshVertices[meshOffset++] * subU;
	                    this._vertices[offset++] = startV + meshVertices[meshOffset] * subV;
	                }
	            }
	            else {
	                offset = i + 4;
	            }
	            this._vertices[offset++] = position.x;
	            this._vertices[offset++] = position.y;
	            this._vertices[offset++] = position.z;
	            this._vertices[offset++] = ShurikenParticleData.startLifeTime;
	            this._vertices[offset++] = direction.x;
	            this._vertices[offset++] = direction.y;
	            this._vertices[offset++] = direction.z;
	            this._vertices[offset++] = time;
	            this._vertices[offset++] = ShurikenParticleData.startColor.x;
	            this._vertices[offset++] = ShurikenParticleData.startColor.y;
	            this._vertices[offset++] = ShurikenParticleData.startColor.z;
	            this._vertices[offset++] = ShurikenParticleData.startColor.w;
	            this._vertices[offset++] = ShurikenParticleData.startSize[0];
	            this._vertices[offset++] = ShurikenParticleData.startSize[1];
	            this._vertices[offset++] = ShurikenParticleData.startSize[2];
	            this._vertices[offset++] = ShurikenParticleData.startRotation[0];
	            this._vertices[offset++] = ShurikenParticleData.startRotation[1];
	            this._vertices[offset++] = ShurikenParticleData.startRotation[2];
	            this._vertices[offset++] = startSpeed;
	            needRandomColor && (this._vertices[offset + 1] = randomColor);
	            needRandomSize && (this._vertices[offset + 2] = randomSize);
	            needRandomRotation && (this._vertices[offset + 3] = randomRotation);
	            needRandomTextureAnimation && (this._vertices[offset + 4] = randomTextureAnimation);
	            if (needRandomVelocity) {
	                this._vertices[offset + 5] = randomVelocityX;
	                this._vertices[offset + 6] = randomVelocityY;
	                this._vertices[offset + 7] = randomVelocityZ;
	            }
	            switch (this.simulationSpace) {
	                case 0:
	                    offset += 8;
	                    this._vertices[offset++] = pos.x;
	                    this._vertices[offset++] = pos.y;
	                    this._vertices[offset++] = pos.z;
	                    this._vertices[offset++] = rot.x;
	                    this._vertices[offset++] = rot.y;
	                    this._vertices[offset++] = rot.z;
	                    this._vertices[offset++] = rot.w;
	                    break;
	                case 1:
	                    break;
	                default:
	                    throw new Error("ShurikenParticleMaterial: SimulationSpace value is invalid.");
	            }
	        }
	        this._firstFreeElement = nextFreeParticle;
	        return true;
	    }
	    addNewParticlesToVertexBuffer() {
	        var start;
	        var byteStride = this._vertexStride * this._floatCountPerVertex * 4;
	        if (this._firstNewElement < this._firstFreeElement) {
	            start = this._firstNewElement * byteStride;
	            this._vertexBuffer.setData(this._vertices.buffer, start, start, (this._firstFreeElement - this._firstNewElement) * byteStride);
	        }
	        else {
	            start = this._firstNewElement * byteStride;
	            this._vertexBuffer.setData(this._vertices.buffer, start, start, (this._bufferMaxParticles - this._firstNewElement) * byteStride);
	            if (this._firstFreeElement > 0) {
	                this._vertexBuffer.setData(this._vertices.buffer, 0, 0, this._firstFreeElement * byteStride);
	            }
	        }
	        this._firstNewElement = this._firstFreeElement;
	    }
	    _getType() {
	        return ShurikenParticleSystem._type;
	    }
	    _prepareRender(state) {
	        this._updateEmission();
	        if (this._firstNewElement != this._firstFreeElement)
	            this.addNewParticlesToVertexBuffer();
	        this._drawCounter++;
	        if (this._firstActiveElement != this._firstFreeElement)
	            return true;
	        else
	            return false;
	    }
	    _render(state) {
	        this._bufferState.bind();
	        var indexCount;
	        var gl = Laya.LayaGL.instance;
	        if (this._firstActiveElement < this._firstFreeElement) {
	            indexCount = (this._firstFreeElement - this._firstActiveElement) * this._indexStride;
	            gl.drawElements(gl.TRIANGLES, indexCount, gl.UNSIGNED_SHORT, 2 * this._firstActiveElement * this._indexStride);
	            Laya.Stat.trianglesFaces += indexCount / 3;
	            Laya.Stat.renderBatches++;
	        }
	        else {
	            indexCount = (this._bufferMaxParticles - this._firstActiveElement) * this._indexStride;
	            gl.drawElements(gl.TRIANGLES, indexCount, gl.UNSIGNED_SHORT, 2 * this._firstActiveElement * this._indexStride);
	            Laya.Stat.trianglesFaces += indexCount / 3;
	            Laya.Stat.renderBatches++;
	            if (this._firstFreeElement > 0) {
	                indexCount = this._firstFreeElement * this._indexStride;
	                gl.drawElements(gl.TRIANGLES, indexCount, gl.UNSIGNED_SHORT, 0);
	                Laya.Stat.trianglesFaces += indexCount / 3;
	                Laya.Stat.renderBatches++;
	            }
	        }
	    }
	    play() {
	        this._burstsIndex = 0;
	        this._isEmitting = true;
	        this._isPlaying = true;
	        this._isPaused = false;
	        this._emissionTime = 0;
	        this._totalDelayTime = 0;
	        if (!this.autoRandomSeed) {
	            for (var i = 0, n = this._randomSeeds.length; i < n; i++)
	                this._randomSeeds[i] = this.randomSeed[0] + ShurikenParticleSystem._RANDOMOFFSET[i];
	        }
	        switch (this.startDelayType) {
	            case 0:
	                this._playStartDelay = this.startDelay;
	                break;
	            case 1:
	                if (this.autoRandomSeed) {
	                    this._playStartDelay = Laya.MathUtil.lerp(this.startDelayMin, this.startDelayMax, Math.random());
	                }
	                else {
	                    this._rand.seed = this._randomSeeds[2];
	                    this._playStartDelay = Laya.MathUtil.lerp(this.startDelayMin, this.startDelayMax, this._rand.getFloat());
	                    this._randomSeeds[2] = this._rand.seed;
	                }
	                break;
	            default:
	                throw new Error("Utils3D: startDelayType is invalid.");
	        }
	        this._frameRateTime = this._currentTime + this._playStartDelay;
	        this._startUpdateLoopCount = Laya.Stat.loopCount;
	    }
	    pause() {
	        this._isPaused = true;
	    }
	    simulate(time, restart = true) {
	        this._simulateUpdate = true;
	        if (restart) {
	            this._updateParticlesSimulationRestart(time);
	        }
	        else {
	            this._isPaused = false;
	            this._updateParticles(time);
	        }
	        this.pause();
	    }
	    stop() {
	        this._burstsIndex = 0;
	        this._isEmitting = false;
	        this._emissionTime = 0;
	    }
	    cloneTo(destObject) {
	        var dest = destObject;
	        dest.duration = this.duration;
	        dest.looping = this.looping;
	        dest.prewarm = this.prewarm;
	        dest.startDelayType = this.startDelayType;
	        dest.startDelay = this.startDelay;
	        dest.startDelayMin = this.startDelayMin;
	        dest.startDelayMax = this.startDelayMax;
	        dest._maxStartLifetime = this._maxStartLifetime;
	        dest.startLifetimeType = this.startLifetimeType;
	        dest.startLifetimeConstant = this.startLifetimeConstant;
	        this.startLifeTimeGradient.cloneTo(dest.startLifeTimeGradient);
	        dest.startLifetimeConstantMin = this.startLifetimeConstantMin;
	        dest.startLifetimeConstantMax = this.startLifetimeConstantMax;
	        this.startLifeTimeGradientMin.cloneTo(dest.startLifeTimeGradientMin);
	        this.startLifeTimeGradientMax.cloneTo(dest.startLifeTimeGradientMax);
	        dest.startSpeedType = this.startSpeedType;
	        dest.startSpeedConstant = this.startSpeedConstant;
	        dest.startSpeedConstantMin = this.startSpeedConstantMin;
	        dest.startSpeedConstantMax = this.startSpeedConstantMax;
	        dest.threeDStartSize = this.threeDStartSize;
	        dest.startSizeType = this.startSizeType;
	        dest.startSizeConstant = this.startSizeConstant;
	        this.startSizeConstantSeparate.cloneTo(dest.startSizeConstantSeparate);
	        dest.startSizeConstantMin = this.startSizeConstantMin;
	        dest.startSizeConstantMax = this.startSizeConstantMax;
	        this.startSizeConstantMinSeparate.cloneTo(dest.startSizeConstantMinSeparate);
	        this.startSizeConstantMaxSeparate.cloneTo(dest.startSizeConstantMaxSeparate);
	        dest.threeDStartRotation = this.threeDStartRotation;
	        dest.startRotationType = this.startRotationType;
	        dest.startRotationConstant = this.startRotationConstant;
	        this.startRotationConstantSeparate.cloneTo(dest.startRotationConstantSeparate);
	        dest.startRotationConstantMin = this.startRotationConstantMin;
	        dest.startRotationConstantMax = this.startRotationConstantMax;
	        this.startRotationConstantMinSeparate.cloneTo(dest.startRotationConstantMinSeparate);
	        this.startRotationConstantMaxSeparate.cloneTo(dest.startRotationConstantMaxSeparate);
	        dest.randomizeRotationDirection = this.randomizeRotationDirection;
	        dest.startColorType = this.startColorType;
	        this.startColorConstant.cloneTo(dest.startColorConstant);
	        this.startColorConstantMin.cloneTo(dest.startColorConstantMin);
	        this.startColorConstantMax.cloneTo(dest.startColorConstantMax);
	        dest.gravityModifier = this.gravityModifier;
	        dest.simulationSpace = this.simulationSpace;
	        dest.scaleMode = this.scaleMode;
	        dest.playOnAwake = this.playOnAwake;
	        dest.autoRandomSeed = this.autoRandomSeed;
	        dest.randomSeed[0] = this.randomSeed[0];
	        dest.maxParticles = this.maxParticles;
	        (this._emission) && (dest._emission = this._emission.clone());
	        (this.shape) && (dest.shape = this.shape.clone());
	        (this.velocityOverLifetime) && (dest.velocityOverLifetime = this.velocityOverLifetime.clone());
	        (this.colorOverLifetime) && (dest.colorOverLifetime = this.colorOverLifetime.clone());
	        (this.sizeOverLifetime) && (dest.sizeOverLifetime = this.sizeOverLifetime.clone());
	        (this.rotationOverLifetime) && (dest.rotationOverLifetime = this.rotationOverLifetime.clone());
	        (this.textureSheetAnimation) && (dest.textureSheetAnimation = this.textureSheetAnimation.clone());
	        dest.isPerformanceMode = this.isPerformanceMode;
	        dest._isEmitting = this._isEmitting;
	        dest._isPlaying = this._isPlaying;
	        dest._isPaused = this._isPaused;
	        dest._playStartDelay = this._playStartDelay;
	        dest._frameRateTime = this._frameRateTime;
	        dest._emissionTime = this._emissionTime;
	        dest._totalDelayTime = this._totalDelayTime;
	        dest._burstsIndex = this._burstsIndex;
	    }
	    clone() {
	        var dest = new ShurikenParticleSystem(null);
	        this.cloneTo(dest);
	        return dest;
	    }
	}
	ShurikenParticleSystem._RANDOMOFFSET = new Uint32Array([0x23571a3e, 0xc34f56fe, 0x13371337, 0x12460f3b, 0x6aed452e, 0xdec4aea1, 0x96aa4de3, 0x8d2c8431, 0xf3857f6f, 0xe0fbd834, 0x13740583, 0x591bc05c, 0x40eb95e4, 0xbc524e5f, 0xaf502044, 0xa614b381, 0x1034e524, 0xfc524e5f]);
	ShurikenParticleSystem.halfKSqrtOf2 = 1.42 * 0.5;
	ShurikenParticleSystem._maxElapsedTime = 1.0 / 3.0;
	ShurikenParticleSystem._tempVector30 = new Vector3();
	ShurikenParticleSystem._tempVector31 = new Vector3();
	ShurikenParticleSystem._tempVector32 = new Vector3();
	ShurikenParticleSystem._tempVector33 = new Vector3();
	ShurikenParticleSystem._tempVector34 = new Vector3();
	ShurikenParticleSystem._tempVector35 = new Vector3();
	ShurikenParticleSystem._tempVector36 = new Vector3();
	ShurikenParticleSystem._tempVector37 = new Vector3();
	ShurikenParticleSystem._tempVector38 = new Vector3();
	ShurikenParticleSystem._tempVector39 = new Vector3();
	ShurikenParticleSystem._tempPosition = new Vector3();
	ShurikenParticleSystem._tempDirection = new Vector3();
	ShurikenParticleSystem._type = GeometryElement._typeCounter++;

	class Burst {
	    get time() {
	        return this._time;
	    }
	    get minCount() {
	        return this._minCount;
	    }
	    get maxCount() {
	        return this._maxCount;
	    }
	    constructor(time, minCount, maxCount) {
	        this._time = time;
	        this._minCount = minCount;
	        this._maxCount = maxCount;
	    }
	    cloneTo(destObject) {
	        var destBurst = destObject;
	        destBurst._time = this._time;
	        destBurst._minCount = this._minCount;
	        destBurst._maxCount = this._maxCount;
	    }
	    clone() {
	        var destBurst = new Burst(this._time, this._minCount, this._maxCount);
	        this.cloneTo(destBurst);
	        return destBurst;
	    }
	}

	class GradientColor {
	    constructor() {
	        this._type = 0;
	        this._constant = null;
	        this._constantMin = null;
	        this._constantMax = null;
	        this._gradient = null;
	        this._gradientMin = null;
	        this._gradientMax = null;
	    }
	    static createByConstant(constant) {
	        var gradientColor = new GradientColor();
	        gradientColor._type = 0;
	        gradientColor._constant = constant;
	        return gradientColor;
	    }
	    static createByGradient(gradient) {
	        var gradientColor = new GradientColor();
	        gradientColor._type = 1;
	        gradientColor._gradient = gradient;
	        return gradientColor;
	    }
	    static createByRandomTwoConstant(minConstant, maxConstant) {
	        var gradientColor = new GradientColor();
	        gradientColor._type = 2;
	        gradientColor._constantMin = minConstant;
	        gradientColor._constantMax = maxConstant;
	        return gradientColor;
	    }
	    static createByRandomTwoGradient(minGradient, maxGradient) {
	        var gradientColor = new GradientColor();
	        gradientColor._type = 3;
	        gradientColor._gradientMin = minGradient;
	        gradientColor._gradientMax = maxGradient;
	        return gradientColor;
	    }
	    get type() {
	        return this._type;
	    }
	    get constant() {
	        return this._constant;
	    }
	    get constantMin() {
	        return this._constantMin;
	    }
	    get constantMax() {
	        return this._constantMax;
	    }
	    get gradient() {
	        return this._gradient;
	    }
	    get gradientMin() {
	        return this._gradientMin;
	    }
	    get gradientMax() {
	        return this._gradientMax;
	    }
	    cloneTo(destObject) {
	        var destGradientColor = destObject;
	        destGradientColor._type = this._type;
	        this._constant.cloneTo(destGradientColor._constant);
	        this._constantMin.cloneTo(destGradientColor._constantMin);
	        this._constantMax.cloneTo(destGradientColor._constantMax);
	        this._gradient.cloneTo(destGradientColor._gradient);
	        this._gradientMin.cloneTo(destGradientColor._gradientMin);
	        this._gradientMax.cloneTo(destGradientColor._gradientMax);
	    }
	    clone() {
	        var destGradientColor = new GradientColor();
	        this.cloneTo(destGradientColor);
	        return destGradientColor;
	    }
	}

	class ColorOverLifetime {
	    get color() {
	        return this._color;
	    }
	    constructor(color) {
	        this._color = color;
	    }
	    cloneTo(destObject) {
	        var destColorOverLifetime = destObject;
	        this._color.cloneTo(destColorOverLifetime._color);
	        destColorOverLifetime.enbale = this.enbale;
	    }
	    clone() {
	        var destColor;
	        switch (this._color.type) {
	            case 0:
	                destColor = GradientColor.createByConstant(this._color.constant.clone());
	                break;
	            case 1:
	                destColor = GradientColor.createByGradient(this._color.gradient.clone());
	                break;
	            case 2:
	                destColor = GradientColor.createByRandomTwoConstant(this._color.constantMin.clone(), this._color.constantMax.clone());
	                break;
	            case 3:
	                destColor = GradientColor.createByRandomTwoGradient(this._color.gradientMin.clone(), this._color.gradientMax.clone());
	                break;
	        }
	        var destColorOverLifetime = new ColorOverLifetime(destColor);
	        destColorOverLifetime.enbale = this.enbale;
	        return destColorOverLifetime;
	    }
	}

	class FrameOverTime {
	    constructor() {
	        this._type = 0;
	        this._constant = 0;
	        this._overTime = null;
	        this._constantMin = 0;
	        this._constantMax = 0;
	        this._overTimeMin = null;
	        this._overTimeMax = null;
	    }
	    static createByConstant(constant) {
	        var rotationOverLifetime = new FrameOverTime();
	        rotationOverLifetime._type = 0;
	        rotationOverLifetime._constant = constant;
	        return rotationOverLifetime;
	    }
	    static createByOverTime(overTime) {
	        var rotationOverLifetime = new FrameOverTime();
	        rotationOverLifetime._type = 1;
	        rotationOverLifetime._overTime = overTime;
	        return rotationOverLifetime;
	    }
	    static createByRandomTwoConstant(constantMin, constantMax) {
	        var rotationOverLifetime = new FrameOverTime();
	        rotationOverLifetime._type = 2;
	        rotationOverLifetime._constantMin = constantMin;
	        rotationOverLifetime._constantMax = constantMax;
	        return rotationOverLifetime;
	    }
	    static createByRandomTwoOverTime(gradientFrameMin, gradientFrameMax) {
	        var rotationOverLifetime = new FrameOverTime();
	        rotationOverLifetime._type = 3;
	        rotationOverLifetime._overTimeMin = gradientFrameMin;
	        rotationOverLifetime._overTimeMax = gradientFrameMax;
	        return rotationOverLifetime;
	    }
	    get type() {
	        return this._type;
	    }
	    get constant() {
	        return this._constant;
	    }
	    get frameOverTimeData() {
	        return this._overTime;
	    }
	    get constantMin() {
	        return this._constantMin;
	    }
	    get constantMax() {
	        return this._constantMax;
	    }
	    get frameOverTimeDataMin() {
	        return this._overTimeMin;
	    }
	    get frameOverTimeDataMax() {
	        return this._overTimeMax;
	    }
	    cloneTo(destObject) {
	        var destFrameOverTime = destObject;
	        destFrameOverTime._type = this._type;
	        destFrameOverTime._constant = this._constant;
	        (this._overTime) && (this._overTime.cloneTo(destFrameOverTime._overTime));
	        destFrameOverTime._constantMin = this._constantMin;
	        destFrameOverTime._constantMax = this._constantMax;
	        (this._overTimeMin) && (this._overTimeMin.cloneTo(destFrameOverTime._overTimeMin));
	        (this._overTimeMax) && (this._overTimeMax.cloneTo(destFrameOverTime._overTimeMax));
	    }
	    clone() {
	        var destFrameOverTime = new FrameOverTime();
	        this.cloneTo(destFrameOverTime);
	        return destFrameOverTime;
	    }
	}

	class GradientAngularVelocity {
	    constructor() {
	        this._type = 0;
	        this._separateAxes = false;
	        this._constant = 0;
	        this._constantSeparate = null;
	        this._gradient = null;
	        this._gradientX = null;
	        this._gradientY = null;
	        this._gradientZ = null;
	        this._gradientW = null;
	        this._constantMin = 0;
	        this._constantMax = 0;
	        this._constantMinSeparate = null;
	        this._constantMaxSeparate = null;
	        this._gradientMin = null;
	        this._gradientMax = null;
	        this._gradientXMin = null;
	        this._gradientXMax = null;
	        this._gradientYMin = null;
	        this._gradientYMax = null;
	        this._gradientZMin = null;
	        this._gradientZMax = null;
	        this._gradientWMin = null;
	        this._gradientWMax = null;
	    }
	    static createByConstant(constant) {
	        var gradientAngularVelocity = new GradientAngularVelocity();
	        gradientAngularVelocity._type = 0;
	        gradientAngularVelocity._separateAxes = false;
	        gradientAngularVelocity._constant = constant;
	        return gradientAngularVelocity;
	    }
	    static createByConstantSeparate(separateConstant) {
	        var gradientAngularVelocity = new GradientAngularVelocity();
	        gradientAngularVelocity._type = 0;
	        gradientAngularVelocity._separateAxes = true;
	        gradientAngularVelocity._constantSeparate = separateConstant;
	        return gradientAngularVelocity;
	    }
	    static createByGradient(gradient) {
	        var gradientAngularVelocity = new GradientAngularVelocity();
	        gradientAngularVelocity._type = 1;
	        gradientAngularVelocity._separateAxes = false;
	        gradientAngularVelocity._gradient = gradient;
	        return gradientAngularVelocity;
	    }
	    static createByGradientSeparate(gradientX, gradientY, gradientZ) {
	        var gradientAngularVelocity = new GradientAngularVelocity();
	        gradientAngularVelocity._type = 1;
	        gradientAngularVelocity._separateAxes = true;
	        gradientAngularVelocity._gradientX = gradientX;
	        gradientAngularVelocity._gradientY = gradientY;
	        gradientAngularVelocity._gradientZ = gradientZ;
	        return gradientAngularVelocity;
	    }
	    static createByRandomTwoConstant(constantMin, constantMax) {
	        var gradientAngularVelocity = new GradientAngularVelocity();
	        gradientAngularVelocity._type = 2;
	        gradientAngularVelocity._separateAxes = false;
	        gradientAngularVelocity._constantMin = constantMin;
	        gradientAngularVelocity._constantMax = constantMax;
	        return gradientAngularVelocity;
	    }
	    static createByRandomTwoConstantSeparate(separateConstantMin, separateConstantMax) {
	        var gradientAngularVelocity = new GradientAngularVelocity();
	        gradientAngularVelocity._type = 2;
	        gradientAngularVelocity._separateAxes = true;
	        gradientAngularVelocity._constantMinSeparate = separateConstantMin;
	        gradientAngularVelocity._constantMaxSeparate = separateConstantMax;
	        return gradientAngularVelocity;
	    }
	    static createByRandomTwoGradient(gradientMin, gradientMax) {
	        var gradientAngularVelocity = new GradientAngularVelocity();
	        gradientAngularVelocity._type = 3;
	        gradientAngularVelocity._separateAxes = false;
	        gradientAngularVelocity._gradientMin = gradientMin;
	        gradientAngularVelocity._gradientMax = gradientMax;
	        return gradientAngularVelocity;
	    }
	    static createByRandomTwoGradientSeparate(gradientXMin, gradientXMax, gradientYMin, gradientYMax, gradientZMin, gradientZMax, gradientWMin, gradientWMax) {
	        var gradientAngularVelocity = new GradientAngularVelocity();
	        gradientAngularVelocity._type = 3;
	        gradientAngularVelocity._separateAxes = true;
	        gradientAngularVelocity._gradientXMin = gradientXMin;
	        gradientAngularVelocity._gradientXMax = gradientXMax;
	        gradientAngularVelocity._gradientYMin = gradientYMin;
	        gradientAngularVelocity._gradientYMax = gradientYMax;
	        gradientAngularVelocity._gradientZMin = gradientZMin;
	        gradientAngularVelocity._gradientZMax = gradientZMax;
	        gradientAngularVelocity._gradientWMin = gradientWMin;
	        gradientAngularVelocity._gradientWMax = gradientWMax;
	        return gradientAngularVelocity;
	    }
	    get type() {
	        return this._type;
	    }
	    get separateAxes() {
	        return this._separateAxes;
	    }
	    get constant() {
	        return this._constant;
	    }
	    get constantSeparate() {
	        return this._constantSeparate;
	    }
	    get gradient() {
	        return this._gradient;
	    }
	    get gradientX() {
	        return this._gradientX;
	    }
	    get gradientY() {
	        return this._gradientY;
	    }
	    get gradientZ() {
	        return this._gradientZ;
	    }
	    get gradientW() {
	        return this._gradientW;
	    }
	    get constantMin() {
	        return this._constantMin;
	    }
	    get constantMax() {
	        return this._constantMax;
	    }
	    get constantMinSeparate() {
	        return this._constantMinSeparate;
	    }
	    get constantMaxSeparate() {
	        return this._constantMaxSeparate;
	    }
	    get gradientMin() {
	        return this._gradientMin;
	    }
	    get gradientMax() {
	        return this._gradientMax;
	    }
	    get gradientXMin() {
	        return this._gradientXMin;
	    }
	    get gradientXMax() {
	        return this._gradientXMax;
	    }
	    get gradientYMin() {
	        return this._gradientYMin;
	    }
	    get gradientYMax() {
	        return this._gradientYMax;
	    }
	    get gradientZMin() {
	        return this._gradientZMin;
	    }
	    get gradientZMax() {
	        return this._gradientZMax;
	    }
	    get gradientWMin() {
	        return this._gradientWMin;
	    }
	    get gradientWMax() {
	        return this._gradientWMax;
	    }
	    cloneTo(destObject) {
	        var destGradientAngularVelocity = destObject;
	        destGradientAngularVelocity._type = this._type;
	        destGradientAngularVelocity._separateAxes = this._separateAxes;
	        destGradientAngularVelocity._constant = this._constant;
	        this._constantSeparate.cloneTo(destGradientAngularVelocity._constantSeparate);
	        this._gradient.cloneTo(destGradientAngularVelocity._gradient);
	        this._gradientX.cloneTo(destGradientAngularVelocity._gradientX);
	        this._gradientY.cloneTo(destGradientAngularVelocity._gradientY);
	        this._gradientZ.cloneTo(destGradientAngularVelocity._gradientZ);
	        destGradientAngularVelocity._constantMin = this._constantMin;
	        destGradientAngularVelocity._constantMax = this._constantMax;
	        this._constantMinSeparate.cloneTo(destGradientAngularVelocity._constantMinSeparate);
	        this._constantMaxSeparate.cloneTo(destGradientAngularVelocity._constantMaxSeparate);
	        this._gradientMin.cloneTo(destGradientAngularVelocity._gradientMin);
	        this._gradientMax.cloneTo(destGradientAngularVelocity._gradientMax);
	        this._gradientXMin.cloneTo(destGradientAngularVelocity._gradientXMin);
	        this._gradientXMax.cloneTo(destGradientAngularVelocity._gradientXMax);
	        this._gradientYMin.cloneTo(destGradientAngularVelocity._gradientYMin);
	        this._gradientYMax.cloneTo(destGradientAngularVelocity._gradientYMax);
	        this._gradientZMin.cloneTo(destGradientAngularVelocity._gradientZMin);
	        this._gradientZMax.cloneTo(destGradientAngularVelocity._gradientZMax);
	    }
	    clone() {
	        var destGradientAngularVelocity = new GradientAngularVelocity();
	        this.cloneTo(destGradientAngularVelocity);
	        return destGradientAngularVelocity;
	    }
	}

	class GradientDataInt {
	    constructor() {
	        this._currentLength = 0;
	        this._elements = new Float32Array(8);
	    }
	    get gradientCount() {
	        return this._currentLength / 2;
	    }
	    add(key, value) {
	        if (this._currentLength < 8) {
	            if ((this._currentLength === 6) && ((key !== 1))) {
	                key = 1;
	                console.log("Warning:the forth key is  be force set to 1.");
	            }
	            this._elements[this._currentLength++] = key;
	            this._elements[this._currentLength++] = value;
	        }
	        else {
	            console.log("Warning:data count must lessEqual than 4");
	        }
	    }
	    cloneTo(destObject) {
	        var destGradientDataInt = destObject;
	        destGradientDataInt._currentLength = this._currentLength;
	        var destElements = destGradientDataInt._elements;
	        for (var i = 0, n = this._elements.length; i < n; i++) {
	            destElements[i] = this._elements[i];
	        }
	    }
	    clone() {
	        var destGradientDataInt = new GradientDataInt();
	        this.cloneTo(destGradientDataInt);
	        return destGradientDataInt;
	    }
	}

	class GradientSize {
	    constructor() {
	        this._type = 0;
	        this._separateAxes = false;
	        this._gradient = null;
	        this._gradientX = null;
	        this._gradientY = null;
	        this._gradientZ = null;
	        this._constantMin = 0;
	        this._constantMax = 0;
	        this._constantMinSeparate = null;
	        this._constantMaxSeparate = null;
	        this._gradientMin = null;
	        this._gradientMax = null;
	        this._gradientXMin = null;
	        this._gradientXMax = null;
	        this._gradientYMin = null;
	        this._gradientYMax = null;
	        this._gradientZMin = null;
	        this._gradientZMax = null;
	    }
	    static createByGradient(gradient) {
	        var gradientSize = new GradientSize();
	        gradientSize._type = 0;
	        gradientSize._separateAxes = false;
	        gradientSize._gradient = gradient;
	        return gradientSize;
	    }
	    static createByGradientSeparate(gradientX, gradientY, gradientZ) {
	        var gradientSize = new GradientSize();
	        gradientSize._type = 0;
	        gradientSize._separateAxes = true;
	        gradientSize._gradientX = gradientX;
	        gradientSize._gradientY = gradientY;
	        gradientSize._gradientZ = gradientZ;
	        return gradientSize;
	    }
	    static createByRandomTwoConstant(constantMin, constantMax) {
	        var gradientSize = new GradientSize();
	        gradientSize._type = 1;
	        gradientSize._separateAxes = false;
	        gradientSize._constantMin = constantMin;
	        gradientSize._constantMax = constantMax;
	        return gradientSize;
	    }
	    static createByRandomTwoConstantSeparate(constantMinSeparate, constantMaxSeparate) {
	        var gradientSize = new GradientSize();
	        gradientSize._type = 1;
	        gradientSize._separateAxes = true;
	        gradientSize._constantMinSeparate = constantMinSeparate;
	        gradientSize._constantMaxSeparate = constantMaxSeparate;
	        return gradientSize;
	    }
	    static createByRandomTwoGradient(gradientMin, gradientMax) {
	        var gradientSize = new GradientSize();
	        gradientSize._type = 2;
	        gradientSize._separateAxes = false;
	        gradientSize._gradientMin = gradientMin;
	        gradientSize._gradientMax = gradientMax;
	        return gradientSize;
	    }
	    static createByRandomTwoGradientSeparate(gradientXMin, gradientXMax, gradientYMin, gradientYMax, gradientZMin, gradientZMax) {
	        var gradientSize = new GradientSize();
	        gradientSize._type = 2;
	        gradientSize._separateAxes = true;
	        gradientSize._gradientXMin = gradientXMin;
	        gradientSize._gradientXMax = gradientXMax;
	        gradientSize._gradientYMin = gradientYMin;
	        gradientSize._gradientYMax = gradientYMax;
	        gradientSize._gradientZMin = gradientZMin;
	        gradientSize._gradientZMax = gradientZMax;
	        return gradientSize;
	    }
	    get type() {
	        return this._type;
	    }
	    get separateAxes() {
	        return this._separateAxes;
	    }
	    get gradient() {
	        return this._gradient;
	    }
	    get gradientX() {
	        return this._gradientX;
	    }
	    get gradientY() {
	        return this._gradientY;
	    }
	    get gradientZ() {
	        return this._gradientZ;
	    }
	    get constantMin() {
	        return this._constantMin;
	    }
	    get constantMax() {
	        return this._constantMax;
	    }
	    get constantMinSeparate() {
	        return this._constantMinSeparate;
	    }
	    get constantMaxSeparate() {
	        return this._constantMaxSeparate;
	    }
	    get gradientMin() {
	        return this._gradientMin;
	    }
	    get gradientMax() {
	        return this._gradientMax;
	    }
	    get gradientXMin() {
	        return this._gradientXMin;
	    }
	    get gradientXMax() {
	        return this._gradientXMax;
	    }
	    get gradientYMin() {
	        return this._gradientYMin;
	    }
	    get gradientYMax() {
	        return this._gradientYMax;
	    }
	    get gradientZMin() {
	        return this._gradientZMin;
	    }
	    get gradientZMax() {
	        return this._gradientZMax;
	    }
	    getMaxSizeInGradient() {
	        var i, n;
	        var maxSize = -Number.MAX_VALUE;
	        switch (this._type) {
	            case 0:
	                if (this._separateAxes) {
	                    for (i = 0, n = this._gradientX.gradientCount; i < n; i++)
	                        maxSize = Math.max(maxSize, this._gradientX.getValueByIndex(i));
	                    for (i = 0, n = this._gradientY.gradientCount; i < n; i++)
	                        maxSize = Math.max(maxSize, this._gradientY.getValueByIndex(i));
	                }
	                else {
	                    for (i = 0, n = this._gradient.gradientCount; i < n; i++)
	                        maxSize = Math.max(maxSize, this._gradient.getValueByIndex(i));
	                }
	                break;
	            case 1:
	                if (this._separateAxes) {
	                    maxSize = Math.max(this._constantMinSeparate.x, this._constantMaxSeparate.x);
	                    maxSize = Math.max(maxSize, this._constantMinSeparate.y);
	                    maxSize = Math.max(maxSize, this._constantMaxSeparate.y);
	                }
	                else {
	                    maxSize = Math.max(this._constantMin, this._constantMax);
	                }
	                break;
	            case 2:
	                if (this._separateAxes) {
	                    for (i = 0, n = this._gradientXMin.gradientCount; i < n; i++)
	                        maxSize = Math.max(maxSize, this._gradientXMin.getValueByIndex(i));
	                    for (i = 0, n = this._gradientXMax.gradientCount; i < n; i++)
	                        maxSize = Math.max(maxSize, this._gradientXMax.getValueByIndex(i));
	                    for (i = 0, n = this._gradientYMin.gradientCount; i < n; i++)
	                        maxSize = Math.max(maxSize, this._gradientYMin.getValueByIndex(i));
	                    for (i = 0, n = this._gradientZMax.gradientCount; i < n; i++)
	                        maxSize = Math.max(maxSize, this._gradientZMax.getValueByIndex(i));
	                }
	                else {
	                    for (i = 0, n = this._gradientMin.gradientCount; i < n; i++)
	                        maxSize = Math.max(maxSize, this._gradientMin.getValueByIndex(i));
	                    for (i = 0, n = this._gradientMax.gradientCount; i < n; i++)
	                        maxSize = Math.max(maxSize, this._gradientMax.getValueByIndex(i));
	                }
	                break;
	        }
	        return maxSize;
	    }
	    cloneTo(destObject) {
	        var destGradientSize = destObject;
	        destGradientSize._type = this._type;
	        destGradientSize._separateAxes = this._separateAxes;
	        this._gradient.cloneTo(destGradientSize._gradient);
	        this._gradientX.cloneTo(destGradientSize._gradientX);
	        this._gradientY.cloneTo(destGradientSize._gradientY);
	        this._gradientZ.cloneTo(destGradientSize._gradientZ);
	        destGradientSize._constantMin = this._constantMin;
	        destGradientSize._constantMax = this._constantMax;
	        this._constantMinSeparate.cloneTo(destGradientSize._constantMinSeparate);
	        this._constantMaxSeparate.cloneTo(destGradientSize._constantMaxSeparate);
	        this._gradientMin.cloneTo(destGradientSize._gradientMin);
	        this._gradientMax.cloneTo(destGradientSize._gradientMax);
	        this._gradientXMin.cloneTo(destGradientSize._gradientXMin);
	        this._gradientXMax.cloneTo(destGradientSize._gradientXMax);
	        this._gradientYMin.cloneTo(destGradientSize._gradientYMin);
	        this._gradientYMax.cloneTo(destGradientSize._gradientYMax);
	        this._gradientZMin.cloneTo(destGradientSize._gradientZMin);
	        this._gradientZMax.cloneTo(destGradientSize._gradientZMax);
	    }
	    clone() {
	        var destGradientSize = new GradientSize();
	        this.cloneTo(destGradientSize);
	        return destGradientSize;
	    }
	}

	class GradientVelocity {
	    constructor() {
	        this._type = 0;
	        this._constant = null;
	        this._gradientX = null;
	        this._gradientY = null;
	        this._gradientZ = null;
	        this._constantMin = null;
	        this._constantMax = null;
	        this._gradientXMin = null;
	        this._gradientXMax = null;
	        this._gradientYMin = null;
	        this._gradientYMax = null;
	        this._gradientZMin = null;
	        this._gradientZMax = null;
	    }
	    static createByConstant(constant) {
	        var gradientVelocity = new GradientVelocity();
	        gradientVelocity._type = 0;
	        gradientVelocity._constant = constant;
	        return gradientVelocity;
	    }
	    static createByGradient(gradientX, gradientY, gradientZ) {
	        var gradientVelocity = new GradientVelocity();
	        gradientVelocity._type = 1;
	        gradientVelocity._gradientX = gradientX;
	        gradientVelocity._gradientY = gradientY;
	        gradientVelocity._gradientZ = gradientZ;
	        return gradientVelocity;
	    }
	    static createByRandomTwoConstant(constantMin, constantMax) {
	        var gradientVelocity = new GradientVelocity();
	        gradientVelocity._type = 2;
	        gradientVelocity._constantMin = constantMin;
	        gradientVelocity._constantMax = constantMax;
	        return gradientVelocity;
	    }
	    static createByRandomTwoGradient(gradientXMin, gradientXMax, gradientYMin, gradientYMax, gradientZMin, gradientZMax) {
	        var gradientVelocity = new GradientVelocity();
	        gradientVelocity._type = 3;
	        gradientVelocity._gradientXMin = gradientXMin;
	        gradientVelocity._gradientXMax = gradientXMax;
	        gradientVelocity._gradientYMin = gradientYMin;
	        gradientVelocity._gradientYMax = gradientYMax;
	        gradientVelocity._gradientZMin = gradientZMin;
	        gradientVelocity._gradientZMax = gradientZMax;
	        return gradientVelocity;
	    }
	    get type() {
	        return this._type;
	    }
	    get constant() {
	        return this._constant;
	    }
	    get gradientX() {
	        return this._gradientX;
	    }
	    get gradientY() {
	        return this._gradientY;
	    }
	    get gradientZ() {
	        return this._gradientZ;
	    }
	    get constantMin() {
	        return this._constantMin;
	    }
	    get constantMax() {
	        return this._constantMax;
	    }
	    get gradientXMin() {
	        return this._gradientXMin;
	    }
	    get gradientXMax() {
	        return this._gradientXMax;
	    }
	    get gradientYMin() {
	        return this._gradientYMin;
	    }
	    get gradientYMax() {
	        return this._gradientYMax;
	    }
	    get gradientZMin() {
	        return this._gradientZMin;
	    }
	    get gradientZMax() {
	        return this._gradientZMax;
	    }
	    cloneTo(destObject) {
	        var destGradientVelocity = destObject;
	        destGradientVelocity._type = this._type;
	        this._constant.cloneTo(destGradientVelocity._constant);
	        this._gradientX.cloneTo(destGradientVelocity._gradientX);
	        this._gradientY.cloneTo(destGradientVelocity._gradientY);
	        this._gradientZ.cloneTo(destGradientVelocity._gradientZ);
	        this._constantMin.cloneTo(destGradientVelocity._constantMin);
	        this._constantMax.cloneTo(destGradientVelocity._constantMax);
	        this._gradientXMin.cloneTo(destGradientVelocity._gradientXMin);
	        this._gradientXMax.cloneTo(destGradientVelocity._gradientXMax);
	        this._gradientYMin.cloneTo(destGradientVelocity._gradientYMin);
	        this._gradientYMax.cloneTo(destGradientVelocity._gradientYMax);
	        this._gradientZMin.cloneTo(destGradientVelocity._gradientZMin);
	        this._gradientZMax.cloneTo(destGradientVelocity._gradientZMax);
	    }
	    clone() {
	        var destGradientVelocity = new GradientVelocity();
	        this.cloneTo(destGradientVelocity);
	        return destGradientVelocity;
	    }
	}

	class RotationOverLifetime {
	    get angularVelocity() {
	        return this._angularVelocity;
	    }
	    constructor(angularVelocity) {
	        this._angularVelocity = angularVelocity;
	    }
	    cloneTo(destObject) {
	        var destRotationOverLifetime = destObject;
	        this._angularVelocity.cloneTo(destRotationOverLifetime._angularVelocity);
	        destRotationOverLifetime.enbale = this.enbale;
	    }
	    clone() {
	        var destAngularVelocity;
	        switch (this._angularVelocity.type) {
	            case 0:
	                if (this._angularVelocity.separateAxes)
	                    destAngularVelocity = GradientAngularVelocity.createByConstantSeparate(this._angularVelocity.constantSeparate.clone());
	                else
	                    destAngularVelocity = GradientAngularVelocity.createByConstant(this._angularVelocity.constant);
	                break;
	            case 1:
	                if (this._angularVelocity.separateAxes)
	                    destAngularVelocity = GradientAngularVelocity.createByGradientSeparate(this._angularVelocity.gradientX.clone(), this._angularVelocity.gradientY.clone(), this._angularVelocity.gradientZ.clone());
	                else
	                    destAngularVelocity = GradientAngularVelocity.createByGradient(this._angularVelocity.gradient.clone());
	                break;
	            case 2:
	                if (this._angularVelocity.separateAxes)
	                    destAngularVelocity = GradientAngularVelocity.createByRandomTwoConstantSeparate(this._angularVelocity.constantMinSeparate.clone(), this._angularVelocity.constantMaxSeparate.clone());
	                else
	                    destAngularVelocity = GradientAngularVelocity.createByRandomTwoConstant(this._angularVelocity.constantMin, this._angularVelocity.constantMax);
	                break;
	            case 3:
	                if (this._angularVelocity.separateAxes)
	                    destAngularVelocity = GradientAngularVelocity.createByRandomTwoGradientSeparate(this._angularVelocity.gradientXMin.clone(), this._angularVelocity.gradientYMin.clone(), this._angularVelocity.gradientZMin.clone(), this._angularVelocity.gradientWMin.clone(), this._angularVelocity.gradientXMax.clone(), this._angularVelocity.gradientYMax.clone(), this._angularVelocity.gradientZMax.clone(), this._angularVelocity.gradientWMax.clone());
	                else
	                    destAngularVelocity = GradientAngularVelocity.createByRandomTwoGradient(this._angularVelocity.gradientMin.clone(), this._angularVelocity.gradientMax.clone());
	                break;
	        }
	        var destRotationOverLifetime = new RotationOverLifetime(destAngularVelocity);
	        destRotationOverLifetime.enbale = this.enbale;
	        return destRotationOverLifetime;
	    }
	}

	class BaseShape {
	    constructor() {
	    }
	    _getShapeBoundBox(boundBox) {
	        throw new Error("BaseShape: must override it.");
	    }
	    _getSpeedBoundBox(boundBox) {
	        throw new Error("BaseShape: must override it.");
	    }
	    generatePositionAndDirection(position, direction, rand = null, randomSeeds = null) {
	        throw new Error("BaseShape: must override it.");
	    }
	    _calculateProceduralBounds(boundBox, emitterPosScale, minMaxBounds) {
	        this._getShapeBoundBox(boundBox);
	        var min = boundBox.min;
	        var max = boundBox.max;
	        Vector3.multiply(min, emitterPosScale, min);
	        Vector3.multiply(max, emitterPosScale, max);
	        var speedBounds = new BoundBox(new Vector3(), new Vector3());
	        if (this.randomDirection) {
	            speedBounds.min = new Vector3(-1, -1, -1);
	            speedBounds.max = new Vector3(1, 1, 1);
	        }
	        else {
	            this._getSpeedBoundBox(speedBounds);
	        }
	        var maxSpeedBound = new BoundBox(new Vector3(), new Vector3());
	        var maxSpeedMin = maxSpeedBound.min;
	        var maxSpeedMax = maxSpeedBound.max;
	        Vector3.scale(speedBounds.min, minMaxBounds.y, maxSpeedMin);
	        Vector3.scale(speedBounds.max, minMaxBounds.y, maxSpeedMax);
	        Vector3.add(boundBox.min, maxSpeedMin, maxSpeedMin);
	        Vector3.add(boundBox.max, maxSpeedMax, maxSpeedMax);
	        Vector3.min(boundBox.min, maxSpeedMin, boundBox.min);
	        Vector3.max(boundBox.max, maxSpeedMin, boundBox.max);
	        var minSpeedBound = new BoundBox(new Vector3(), new Vector3());
	        var minSpeedMin = minSpeedBound.min;
	        var minSpeedMax = minSpeedBound.max;
	        Vector3.scale(speedBounds.min, minMaxBounds.x, minSpeedMin);
	        Vector3.scale(speedBounds.max, minMaxBounds.x, minSpeedMax);
	        Vector3.min(minSpeedBound.min, minSpeedMax, maxSpeedMin);
	        Vector3.max(minSpeedBound.min, minSpeedMax, maxSpeedMax);
	        Vector3.min(boundBox.min, maxSpeedMin, boundBox.min);
	        Vector3.max(boundBox.max, maxSpeedMin, boundBox.max);
	    }
	    cloneTo(destObject) {
	        var destShape = destObject;
	        destShape.enable = this.enable;
	    }
	    clone() {
	        var destShape = new BaseShape();
	        this.cloneTo(destShape);
	        return destShape;
	    }
	}

	class ShapeUtils {
	    static _randomPointUnitArcCircle(arc, out, rand = null) {
	        var angle;
	        if (rand)
	            angle = rand.getFloat() * arc;
	        else
	            angle = Math.random() * arc;
	        out.x = Math.cos(angle);
	        out.y = Math.sin(angle);
	    }
	    static _randomPointInsideUnitArcCircle(arc, out, rand = null) {
	        ShapeUtils._randomPointUnitArcCircle(arc, out, rand);
	        var range;
	        if (rand)
	            range = Math.pow(rand.getFloat(), 1.0 / 2.0);
	        else
	            range = Math.pow(Math.random(), 1.0 / 2.0);
	        out.x = out.x * range;
	        out.y = out.y * range;
	    }
	    static _randomPointUnitCircle(out, rand = null) {
	        var angle;
	        if (rand)
	            angle = rand.getFloat() * Math.PI * 2;
	        else
	            angle = Math.random() * Math.PI * 2;
	        out.x = Math.cos(angle);
	        out.y = Math.sin(angle);
	    }
	    static _randomPointInsideUnitCircle(out, rand = null) {
	        ShapeUtils._randomPointUnitCircle(out);
	        var range;
	        if (rand)
	            range = Math.pow(rand.getFloat(), 1.0 / 2.0);
	        else
	            range = Math.pow(Math.random(), 1.0 / 2.0);
	        out.x = out.x * range;
	        out.y = out.y * range;
	    }
	    static _randomPointUnitSphere(out, rand = null) {
	        var z;
	        var a;
	        if (rand) {
	            z = out.z = rand.getFloat() * 2 - 1.0;
	            a = rand.getFloat() * Math.PI * 2;
	        }
	        else {
	            z = out.z = Math.random() * 2 - 1.0;
	            a = Math.random() * Math.PI * 2;
	        }
	        var r = Math.sqrt(1.0 - z * z);
	        out.x = r * Math.cos(a);
	        out.y = r * Math.sin(a);
	    }
	    static _randomPointInsideUnitSphere(out, rand = null) {
	        ShapeUtils._randomPointUnitSphere(out);
	        var range;
	        if (rand)
	            range = Math.pow(rand.getFloat(), 1.0 / 3.0);
	        else
	            range = Math.pow(Math.random(), 1.0 / 3.0);
	        out.x = out.x * range;
	        out.y = out.y * range;
	        out.z = out.z * range;
	    }
	    static _randomPointInsideHalfUnitBox(out, rand = null) {
	        if (rand) {
	            out.x = (rand.getFloat() - 0.5);
	            out.y = (rand.getFloat() - 0.5);
	            out.z = (rand.getFloat() - 0.5);
	        }
	        else {
	            out.x = (Math.random() - 0.5);
	            out.y = (Math.random() - 0.5);
	            out.z = (Math.random() - 0.5);
	        }
	    }
	    constructor() {
	    }
	}

	class BoxShape extends BaseShape {
	    constructor() {
	        super();
	        this.x = 1.0;
	        this.y = 1.0;
	        this.z = 1.0;
	        this.randomDirection = false;
	    }
	    _getShapeBoundBox(boundBox) {
	        var min = boundBox.min;
	        min.x = -this.x * 0.5;
	        min.y = -this.y * 0.5;
	        min.z = -this.z * 0.5;
	        var max = boundBox.max;
	        max.x = this.x * 0.5;
	        max.y = this.y * 0.5;
	        max.z = this.z * 0.5;
	    }
	    _getSpeedBoundBox(boundBox) {
	        var min = boundBox.min;
	        min.x = 0.0;
	        min.y = 0.0;
	        min.z = 0.0;
	        var max = boundBox.max;
	        max.x = 0.0;
	        max.y = 1.0;
	        max.z = 0.0;
	    }
	    generatePositionAndDirection(position, direction, rand = null, randomSeeds = null) {
	        if (rand) {
	            rand.seed = randomSeeds[16];
	            ShapeUtils._randomPointInsideHalfUnitBox(position, rand);
	            randomSeeds[16] = rand.seed;
	        }
	        else {
	            ShapeUtils._randomPointInsideHalfUnitBox(position);
	        }
	        position.x = this.x * position.x;
	        position.y = this.y * position.y;
	        position.z = this.z * position.z;
	        if (this.randomDirection) {
	            if (rand) {
	                rand.seed = randomSeeds[17];
	                ShapeUtils._randomPointUnitSphere(direction, rand);
	                randomSeeds[17] = rand.seed;
	            }
	            else {
	                ShapeUtils._randomPointUnitSphere(direction);
	            }
	        }
	        else {
	            direction.x = 0.0;
	            direction.y = 0.0;
	            direction.z = 1.0;
	        }
	    }
	    cloneTo(destObject) {
	        super.cloneTo(destObject);
	        var destShape = destObject;
	        destShape.x = this.x;
	        destShape.y = this.y;
	        destShape.z = this.z;
	        destShape.randomDirection = this.randomDirection;
	    }
	    clone() {
	        var destShape = new BoxShape();
	        this.cloneTo(destShape);
	        return destShape;
	    }
	}

	class CircleShape extends BaseShape {
	    constructor() {
	        super();
	        this.radius = 1.0;
	        this.arc = 360.0 / 180.0 * Math.PI;
	        this.emitFromEdge = false;
	        this.randomDirection = false;
	    }
	    _getShapeBoundBox(boundBox) {
	        var min = boundBox.min;
	        min.x = min.z = -this.radius;
	        min.y = 0;
	        var max = boundBox.max;
	        max.x = max.z = this.radius;
	        max.y = 0;
	    }
	    _getSpeedBoundBox(boundBox) {
	        var min = boundBox.min;
	        min.x = min.y = -1;
	        min.z = 0;
	        var max = boundBox.max;
	        max.x = max.y = 1;
	        max.z = 0;
	    }
	    generatePositionAndDirection(position, direction, rand = null, randomSeeds = null) {
	        var positionPoint = CircleShape._tempPositionPoint;
	        if (rand) {
	            rand.seed = randomSeeds[16];
	            if (this.emitFromEdge)
	                ShapeUtils._randomPointUnitArcCircle(this.arc, CircleShape._tempPositionPoint, rand);
	            else
	                ShapeUtils._randomPointInsideUnitArcCircle(this.arc, CircleShape._tempPositionPoint, rand);
	            randomSeeds[16] = rand.seed;
	        }
	        else {
	            if (this.emitFromEdge)
	                ShapeUtils._randomPointUnitArcCircle(this.arc, CircleShape._tempPositionPoint);
	            else
	                ShapeUtils._randomPointInsideUnitArcCircle(this.arc, CircleShape._tempPositionPoint);
	        }
	        position.x = -positionPoint.x;
	        position.y = positionPoint.y;
	        position.z = 0;
	        Vector3.scale(position, this.radius, position);
	        if (this.randomDirection) {
	            if (rand) {
	                rand.seed = randomSeeds[17];
	                ShapeUtils._randomPointUnitSphere(direction, rand);
	                randomSeeds[17] = rand.seed;
	            }
	            else {
	                ShapeUtils._randomPointUnitSphere(direction);
	            }
	        }
	        else {
	            position.cloneTo(direction);
	        }
	    }
	    cloneTo(destObject) {
	        super.cloneTo(destObject);
	        var destShape = destObject;
	        destShape.radius = this.radius;
	        destShape.arc = this.arc;
	        destShape.emitFromEdge = this.emitFromEdge;
	        destShape.randomDirection = this.randomDirection;
	    }
	    clone() {
	        var destShape = new CircleShape();
	        this.cloneTo(destShape);
	        return destShape;
	    }
	}
	CircleShape._tempPositionPoint = new Vector2();

	class ConeShape extends BaseShape {
	    constructor() {
	        super();
	        this.angle = 25.0 / 180.0 * Math.PI;
	        this.radius = 1.0;
	        this.length = 5.0;
	        this.emitType = 0;
	        this.randomDirection = false;
	    }
	    _getShapeBoundBox(boundBox) {
	        const coneRadius2 = this.radius + this.length * Math.sin(this.angle);
	        const coneLength = this.length * Math.cos(this.angle);
	        var min = boundBox.min;
	        min.x = min.y = -coneRadius2;
	        min.z = 0;
	        var max = boundBox.max;
	        max.x = max.y = coneRadius2;
	        max.z = coneLength;
	    }
	    _getSpeedBoundBox(boundBox) {
	        const sinA = Math.sin(this.angle);
	        var min = boundBox.min;
	        min.x = min.y = -sinA;
	        min.z = 0;
	        var max = boundBox.max;
	        max.x = max.y = sinA;
	        max.z = 1;
	    }
	    generatePositionAndDirection(position, direction, rand = null, randomSeeds = null) {
	        var positionPointE = ConeShape._tempPositionPoint;
	        var positionX;
	        var positionY;
	        var directionPointE;
	        var dirCosA = Math.cos(this.angle);
	        var dirSinA = Math.sin(this.angle);
	        switch (this.emitType) {
	            case 0:
	                if (rand) {
	                    rand.seed = randomSeeds[16];
	                    ShapeUtils._randomPointInsideUnitCircle(ConeShape._tempPositionPoint, rand);
	                    randomSeeds[16] = rand.seed;
	                }
	                else {
	                    ShapeUtils._randomPointInsideUnitCircle(ConeShape._tempPositionPoint);
	                }
	                positionX = positionPointE.x;
	                positionY = positionPointE.y;
	                position.x = positionX * this.radius;
	                position.y = positionY * this.radius;
	                position.z = 0;
	                if (this.randomDirection) {
	                    if (rand) {
	                        rand.seed = randomSeeds[17];
	                        ShapeUtils._randomPointInsideUnitCircle(ConeShape._tempDirectionPoint, rand);
	                        randomSeeds[17] = rand.seed;
	                    }
	                    else {
	                        ShapeUtils._randomPointInsideUnitCircle(ConeShape._tempDirectionPoint);
	                    }
	                    directionPointE = ConeShape._tempDirectionPoint;
	                    direction.x = directionPointE.x * dirSinA;
	                    direction.y = directionPointE.y * dirSinA;
	                }
	                else {
	                    direction.x = positionX * dirSinA;
	                    direction.y = positionY * dirSinA;
	                }
	                direction.z = dirCosA;
	                break;
	            case 1:
	                if (rand) {
	                    rand.seed = randomSeeds[16];
	                    ShapeUtils._randomPointUnitCircle(ConeShape._tempPositionPoint, rand);
	                    randomSeeds[16] = rand.seed;
	                }
	                else {
	                    ShapeUtils._randomPointUnitCircle(ConeShape._tempPositionPoint);
	                }
	                positionX = positionPointE.x;
	                positionY = positionPointE.y;
	                position.x = positionX * this.radius;
	                position.y = positionY * this.radius;
	                position.z = 0;
	                if (this.randomDirection) {
	                    if (rand) {
	                        rand.seed = randomSeeds[17];
	                        ShapeUtils._randomPointInsideUnitCircle(ConeShape._tempDirectionPoint, rand);
	                        randomSeeds[17] = rand.seed;
	                    }
	                    else {
	                        ShapeUtils._randomPointInsideUnitCircle(ConeShape._tempDirectionPoint);
	                    }
	                    directionPointE = ConeShape._tempDirectionPoint;
	                    direction.x = directionPointE.x * dirSinA;
	                    direction.y = directionPointE.y * dirSinA;
	                }
	                else {
	                    direction.x = positionX * dirSinA;
	                    direction.y = positionY * dirSinA;
	                }
	                direction.z = dirCosA;
	                break;
	            case 2:
	                if (rand) {
	                    rand.seed = randomSeeds[16];
	                    ShapeUtils._randomPointInsideUnitCircle(ConeShape._tempPositionPoint, rand);
	                }
	                else {
	                    ShapeUtils._randomPointInsideUnitCircle(ConeShape._tempPositionPoint);
	                }
	                positionX = positionPointE.x;
	                positionY = positionPointE.y;
	                position.x = positionX * this.radius;
	                position.y = positionY * this.radius;
	                position.z = 0;
	                direction.x = positionX * dirSinA;
	                direction.y = positionY * dirSinA;
	                direction.z = dirCosA;
	                Vector3.normalize(direction, direction);
	                if (rand) {
	                    Vector3.scale(direction, this.length * rand.getFloat(), direction);
	                    randomSeeds[16] = rand.seed;
	                }
	                else {
	                    Vector3.scale(direction, this.length * Math.random(), direction);
	                }
	                Vector3.add(position, direction, position);
	                if (this.randomDirection) {
	                    if (rand) {
	                        rand.seed = randomSeeds[17];
	                        ShapeUtils._randomPointUnitSphere(direction, rand);
	                        randomSeeds[17] = rand.seed;
	                    }
	                    else {
	                        ShapeUtils._randomPointUnitSphere(direction);
	                    }
	                }
	                break;
	            case 3:
	                if (rand) {
	                    rand.seed = randomSeeds[16];
	                    ShapeUtils._randomPointUnitCircle(ConeShape._tempPositionPoint, rand);
	                }
	                else {
	                    ShapeUtils._randomPointUnitCircle(ConeShape._tempPositionPoint);
	                }
	                positionX = positionPointE.x;
	                positionY = positionPointE.y;
	                position.x = positionX * this.radius;
	                position.y = positionY * this.radius;
	                position.z = 0;
	                direction.x = positionX * dirSinA;
	                direction.y = positionY * dirSinA;
	                direction.z = dirCosA;
	                Vector3.normalize(direction, direction);
	                if (rand) {
	                    Vector3.scale(direction, this.length * rand.getFloat(), direction);
	                    randomSeeds[16] = rand.seed;
	                }
	                else {
	                    Vector3.scale(direction, this.length * Math.random(), direction);
	                }
	                Vector3.add(position, direction, position);
	                if (this.randomDirection) {
	                    if (rand) {
	                        rand.seed = randomSeeds[17];
	                        ShapeUtils._randomPointUnitSphere(direction, rand);
	                        randomSeeds[17] = rand.seed;
	                    }
	                    else {
	                        ShapeUtils._randomPointUnitSphere(direction);
	                    }
	                }
	                break;
	            default:
	                throw new Error("ConeShape:emitType is invalid.");
	        }
	    }
	    cloneTo(destObject) {
	        super.cloneTo(destObject);
	        var destShape = destObject;
	        destShape.angle = this.angle;
	        destShape.radius = this.radius;
	        destShape.length = this.length;
	        destShape.emitType = this.emitType;
	        destShape.randomDirection = this.randomDirection;
	    }
	    clone() {
	        var destShape = new ConeShape();
	        this.cloneTo(destShape);
	        return destShape;
	    }
	}
	ConeShape._tempPositionPoint = new Vector2();
	ConeShape._tempDirectionPoint = new Vector2();

	class HemisphereShape extends BaseShape {
	    constructor() {
	        super();
	        this.radius = 1.0;
	        this.emitFromShell = false;
	        this.randomDirection = false;
	    }
	    _getShapeBoundBox(boundBox) {
	        var min = boundBox.min;
	        min.x = min.y = min.z = -this.radius;
	        var max = boundBox.max;
	        max.x = max.y = this.radius;
	        max.z = 0;
	    }
	    _getSpeedBoundBox(boundBox) {
	        var min = boundBox.min;
	        min.x = min.y = -1;
	        min.z = 0;
	        var max = boundBox.max;
	        max.x = max.y = max.z = 1;
	    }
	    generatePositionAndDirection(position, direction, rand = null, randomSeeds = null) {
	        if (rand) {
	            rand.seed = randomSeeds[16];
	            if (this.emitFromShell)
	                ShapeUtils._randomPointUnitSphere(position, rand);
	            else
	                ShapeUtils._randomPointInsideUnitSphere(position, rand);
	            randomSeeds[16] = rand.seed;
	        }
	        else {
	            if (this.emitFromShell)
	                ShapeUtils._randomPointUnitSphere(position);
	            else
	                ShapeUtils._randomPointInsideUnitSphere(position);
	        }
	        Vector3.scale(position, this.radius, position);
	        var z = position.z;
	        (z < 0.0) && (position.z = z * -1.0);
	        if (this.randomDirection) {
	            if (rand) {
	                rand.seed = randomSeeds[17];
	                ShapeUtils._randomPointUnitSphere(direction, rand);
	                randomSeeds[17] = rand.seed;
	            }
	            else {
	                ShapeUtils._randomPointUnitSphere(direction);
	            }
	        }
	        else {
	            position.cloneTo(direction);
	        }
	    }
	    cloneTo(destObject) {
	        super.cloneTo(destObject);
	        var destShape = destObject;
	        destShape.radius = this.radius;
	        destShape.emitFromShell = this.emitFromShell;
	        destShape.randomDirection = this.randomDirection;
	    }
	    clone() {
	        var destShape = new HemisphereShape();
	        this.cloneTo(destShape);
	        return destShape;
	    }
	}

	class SphereShape extends BaseShape {
	    constructor() {
	        super();
	        this.radius = 1.0;
	        this.emitFromShell = false;
	        this.randomDirection = false;
	    }
	    _getShapeBoundBox(boundBox) {
	        var min = boundBox.min;
	        min.x = min.y = min.z = -this.radius;
	        var max = boundBox.max;
	        max.x = max.y = max.z = this.radius;
	    }
	    _getSpeedBoundBox(boundBox) {
	        var min = boundBox.min;
	        min.x = min.y = min.z = -1;
	        var max = boundBox.max;
	        max.x = max.y = max.z = 1;
	    }
	    generatePositionAndDirection(position, direction, rand = null, randomSeeds = null) {
	        if (rand) {
	            rand.seed = randomSeeds[16];
	            if (this.emitFromShell)
	                ShapeUtils._randomPointUnitSphere(position, rand);
	            else
	                ShapeUtils._randomPointInsideUnitSphere(position, rand);
	            randomSeeds[16] = rand.seed;
	        }
	        else {
	            if (this.emitFromShell)
	                ShapeUtils._randomPointUnitSphere(position);
	            else
	                ShapeUtils._randomPointInsideUnitSphere(position);
	        }
	        Vector3.scale(position, this.radius, position);
	        if (this.randomDirection) {
	            if (rand) {
	                rand.seed = randomSeeds[17];
	                ShapeUtils._randomPointUnitSphere(direction, rand);
	                randomSeeds[17] = rand.seed;
	            }
	            else {
	                ShapeUtils._randomPointUnitSphere(direction);
	            }
	        }
	        else {
	            position.cloneTo(direction);
	        }
	    }
	    cloneTo(destObject) {
	        super.cloneTo(destObject);
	        var destShape = destObject;
	        destShape.radius = this.radius;
	        destShape.emitFromShell = this.emitFromShell;
	        destShape.randomDirection = this.randomDirection;
	    }
	    clone() {
	        var destShape = new SphereShape();
	        this.cloneTo(destShape);
	        return destShape;
	    }
	}

	class SizeOverLifetime {
	    get size() {
	        return this._size;
	    }
	    constructor(size) {
	        this._size = size;
	    }
	    cloneTo(destObject) {
	        var destSizeOverLifetime = destObject;
	        this._size.cloneTo(destSizeOverLifetime._size);
	        destSizeOverLifetime.enbale = this.enbale;
	    }
	    clone() {
	        var destSize;
	        switch (this._size.type) {
	            case 0:
	                if (this._size.separateAxes)
	                    destSize = GradientSize.createByGradientSeparate(this._size.gradientX.clone(), this._size.gradientY.clone(), this._size.gradientZ.clone());
	                else
	                    destSize = GradientSize.createByGradient(this._size.gradient.clone());
	                break;
	            case 1:
	                if (this._size.separateAxes)
	                    destSize = GradientSize.createByRandomTwoConstantSeparate(this._size.constantMinSeparate.clone(), this._size.constantMaxSeparate.clone());
	                else
	                    destSize = GradientSize.createByRandomTwoConstant(this._size.constantMin, this._size.constantMax);
	                break;
	            case 2:
	                if (this._size.separateAxes)
	                    destSize = GradientSize.createByRandomTwoGradientSeparate(this._size.gradientXMin.clone(), this._size.gradientYMin.clone(), this._size.gradientZMin.clone(), this._size.gradientXMax.clone(), this._size.gradientYMax.clone(), this._size.gradientZMax.clone());
	                else
	                    destSize = GradientSize.createByRandomTwoGradient(this._size.gradientMin.clone(), this._size.gradientMax.clone());
	                break;
	        }
	        var destSizeOverLifetime = new SizeOverLifetime(destSize);
	        destSizeOverLifetime.enbale = this.enbale;
	        return destSizeOverLifetime;
	    }
	}

	class StartFrame {
	    constructor() {
	        this._type = 0;
	        this._constant = 0;
	        this._constantMin = 0;
	        this._constantMax = 0;
	    }
	    static createByConstant(constant) {
	        var rotationOverLifetime = new StartFrame();
	        rotationOverLifetime._type = 0;
	        rotationOverLifetime._constant = constant;
	        return rotationOverLifetime;
	    }
	    static createByRandomTwoConstant(constantMin, constantMax) {
	        var rotationOverLifetime = new StartFrame();
	        rotationOverLifetime._type = 1;
	        rotationOverLifetime._constantMin = constantMin;
	        rotationOverLifetime._constantMax = constantMax;
	        return rotationOverLifetime;
	    }
	    get type() {
	        return this._type;
	    }
	    get constant() {
	        return this._constant;
	    }
	    get constantMin() {
	        return this._constantMin;
	    }
	    get constantMax() {
	        return this._constantMax;
	    }
	    cloneTo(destObject) {
	        var destStartFrame = destObject;
	        destStartFrame._type = this._type;
	        destStartFrame._constant = this._constant;
	        destStartFrame._constantMin = this._constantMin;
	        destStartFrame._constantMax = this._constantMax;
	    }
	    clone() {
	        var destStartFrame = new StartFrame();
	        this.cloneTo(destStartFrame);
	        return destStartFrame;
	    }
	}

	class TextureSheetAnimation {
	    constructor(frame, startFrame) {
	        this.type = 0;
	        this.randomRow = false;
	        this.rowIndex = 0;
	        this.cycles = 0;
	        this.enableUVChannels = 0;
	        this.enable = false;
	        this.tiles = new Vector2(1, 1);
	        this.type = 0;
	        this.randomRow = true;
	        this.rowIndex = 0;
	        this.cycles = 1;
	        this.enableUVChannels = 1;
	        this._frame = frame;
	        this._startFrame = startFrame;
	    }
	    get frame() {
	        return this._frame;
	    }
	    get startFrame() {
	        return this._startFrame;
	    }
	    cloneTo(destObject) {
	        var destTextureSheetAnimation = destObject;
	        this.tiles.cloneTo(destTextureSheetAnimation.tiles);
	        destTextureSheetAnimation.type = this.type;
	        destTextureSheetAnimation.randomRow = this.randomRow;
	        destTextureSheetAnimation.rowIndex = this.rowIndex;
	        destTextureSheetAnimation.cycles = this.cycles;
	        destTextureSheetAnimation.enableUVChannels = this.enableUVChannels;
	        destTextureSheetAnimation.enable = this.enable;
	        this._frame.cloneTo(destTextureSheetAnimation._frame);
	        this._startFrame.cloneTo(destTextureSheetAnimation._startFrame);
	    }
	    clone() {
	        var destFrame;
	        switch (this._frame.type) {
	            case 0:
	                destFrame = FrameOverTime.createByConstant(this._frame.constant);
	                break;
	            case 1:
	                destFrame = FrameOverTime.createByOverTime(this._frame.frameOverTimeData.clone());
	                break;
	            case 2:
	                destFrame = FrameOverTime.createByRandomTwoConstant(this._frame.constantMin, this._frame.constantMax);
	                break;
	            case 3:
	                destFrame = FrameOverTime.createByRandomTwoOverTime(this._frame.frameOverTimeDataMin.clone(), this._frame.frameOverTimeDataMax.clone());
	                break;
	        }
	        var destStartFrame;
	        switch (this._startFrame.type) {
	            case 0:
	                destStartFrame = StartFrame.createByConstant(this._startFrame.constant);
	                break;
	            case 1:
	                destStartFrame = StartFrame.createByRandomTwoConstant(this._startFrame.constantMin, this._startFrame.constantMax);
	                break;
	        }
	        var destTextureSheetAnimation = new TextureSheetAnimation(destFrame, destStartFrame);
	        this.cloneTo(destTextureSheetAnimation);
	        return destTextureSheetAnimation;
	    }
	}

	class VelocityOverLifetime {
	    constructor(velocity) {
	        this.enbale = false;
	        this.space = 0;
	        this._velocity = velocity;
	    }
	    get velocity() {
	        return this._velocity;
	    }
	    cloneTo(destObject) {
	        var destVelocityOverLifetime = destObject;
	        this._velocity.cloneTo(destVelocityOverLifetime._velocity);
	        destVelocityOverLifetime.enbale = this.enbale;
	        destVelocityOverLifetime.space = this.space;
	    }
	    clone() {
	        var destVelocity;
	        switch (this._velocity.type) {
	            case 0:
	                destVelocity = GradientVelocity.createByConstant(this._velocity.constant.clone());
	                break;
	            case 1:
	                destVelocity = GradientVelocity.createByGradient(this._velocity.gradientX.clone(), this._velocity.gradientY.clone(), this._velocity.gradientZ.clone());
	                break;
	            case 2:
	                destVelocity = GradientVelocity.createByRandomTwoConstant(this._velocity.constantMin.clone(), this._velocity.constantMax.clone());
	                break;
	            case 3:
	                destVelocity = GradientVelocity.createByRandomTwoGradient(this._velocity.gradientXMin.clone(), this._velocity.gradientYMin.clone(), this._velocity.gradientZMin.clone(), this._velocity.gradientXMax.clone(), this._velocity.gradientYMax.clone(), this._velocity.gradientZMax.clone());
	                break;
	        }
	        var destVelocityOverLifetime = new VelocityOverLifetime(destVelocity);
	        destVelocityOverLifetime.enbale = this.enbale;
	        destVelocityOverLifetime.space = this.space;
	        return destVelocityOverLifetime;
	    }
	}

	class ShuriKenParticle3D extends RenderableSprite3D {
	    static __init__() {
	        ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_RENDERMODE_BILLBOARD = Shader3D.getDefineByName("SPHERHBILLBOARD");
	        ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_RENDERMODE_STRETCHEDBILLBOARD = Shader3D.getDefineByName("STRETCHEDBILLBOARD");
	        ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_RENDERMODE_HORIZONTALBILLBOARD = Shader3D.getDefineByName("HORIZONTALBILLBOARD");
	        ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_RENDERMODE_VERTICALBILLBOARD = Shader3D.getDefineByName("VERTICALBILLBOARD");
	        ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_COLOROVERLIFETIME = Shader3D.getDefineByName("COLOROVERLIFETIME");
	        ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_RANDOMCOLOROVERLIFETIME = Shader3D.getDefineByName("RANDOMCOLOROVERLIFETIME");
	        ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_VELOCITYOVERLIFETIMECONSTANT = Shader3D.getDefineByName("VELOCITYOVERLIFETIMECONSTANT");
	        ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_VELOCITYOVERLIFETIMECURVE = Shader3D.getDefineByName("VELOCITYOVERLIFETIMECURVE");
	        ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_VELOCITYOVERLIFETIMERANDOMCONSTANT = Shader3D.getDefineByName("VELOCITYOVERLIFETIMERANDOMCONSTANT");
	        ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_VELOCITYOVERLIFETIMERANDOMCURVE = Shader3D.getDefineByName("VELOCITYOVERLIFETIMERANDOMCURVE");
	        ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_TEXTURESHEETANIMATIONCURVE = Shader3D.getDefineByName("TEXTURESHEETANIMATIONCURVE");
	        ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_TEXTURESHEETANIMATIONRANDOMCURVE = Shader3D.getDefineByName("TEXTURESHEETANIMATIONRANDOMCURVE");
	        ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIME = Shader3D.getDefineByName("ROTATIONOVERLIFETIME");
	        ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMESEPERATE = Shader3D.getDefineByName("ROTATIONOVERLIFETIMESEPERATE");
	        ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMECONSTANT = Shader3D.getDefineByName("ROTATIONOVERLIFETIMECONSTANT");
	        ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMECURVE = Shader3D.getDefineByName("ROTATIONOVERLIFETIMECURVE");
	        ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMERANDOMCONSTANTS = Shader3D.getDefineByName("ROTATIONOVERLIFETIMERANDOMCONSTANTS");
	        ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMERANDOMCURVES = Shader3D.getDefineByName("ROTATIONOVERLIFETIMERANDOMCURVES");
	        ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_SIZEOVERLIFETIMECURVE = Shader3D.getDefineByName("SIZEOVERLIFETIMECURVE");
	        ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_SIZEOVERLIFETIMECURVESEPERATE = Shader3D.getDefineByName("SIZEOVERLIFETIMECURVESEPERATE");
	        ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_SIZEOVERLIFETIMERANDOMCURVES = Shader3D.getDefineByName("SIZEOVERLIFETIMERANDOMCURVES");
	        ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_SIZEOVERLIFETIMERANDOMCURVESSEPERATE = Shader3D.getDefineByName("SIZEOVERLIFETIMERANDOMCURVESSEPERATE");
	        ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_RENDERMODE_MESH = Shader3D.getDefineByName("RENDERMODE_MESH");
	        ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_SHAPE = Shader3D.getDefineByName("SHAPE");
	    }
	    get particleSystem() {
	        return this._particleSystem;
	    }
	    get particleRenderer() {
	        return this._render;
	    }
	    constructor() {
	        super(null);
	        this._render = new ShurikenParticleRenderer(this);
	        this._particleSystem = new ShurikenParticleSystem(this);
	        var elements = this._render._renderElements;
	        var element = elements[0] = new RenderElement();
	        element.setTransform(this._transform);
	        element.render = this._render;
	        element.setGeometry(this._particleSystem);
	        element.material = ShurikenParticleMaterial.defaultMaterial;
	    }
	    static _initStartLife(gradientData) {
	        var gradient = new GradientDataNumber();
	        var startLifetimesData = gradientData.startLifetimes;
	        for (var i = 0, n = startLifetimesData.length; i < n; i++) {
	            var valueData = startLifetimesData[i];
	            gradient.add(valueData.key, valueData.value);
	        }
	        return gradient;
	    }
	    _initParticleVelocity(gradientData) {
	        var gradient = new GradientDataNumber();
	        var velocitysData = gradientData.velocitys;
	        for (var i = 0, n = velocitysData.length; i < n; i++) {
	            var valueData = velocitysData[i];
	            gradient.add(valueData.key, valueData.value);
	        }
	        return gradient;
	    }
	    _initParticleColor(gradientColorData) {
	        var gradientColor = new Gradient(4, 4);
	        var alphasData = gradientColorData.alphas;
	        var i, n;
	        for (i = 0, n = alphasData.length; i < n; i++) {
	            var alphaData = alphasData[i];
	            if ((i === 3) && ((alphaData.key !== 1))) {
	                alphaData.key = 1;
	                console.log("GradientDataColor warning:the forth key is  be force set to 1.");
	            }
	            gradientColor.addColorAlpha(alphaData.key, alphaData.value);
	        }
	        var rgbsData = gradientColorData.rgbs;
	        for (i = 0, n = rgbsData.length; i < n; i++) {
	            var rgbData = rgbsData[i];
	            var rgbValue = rgbData.value;
	            if ((i === 3) && ((rgbData.key !== 1))) {
	                rgbData.key = 1;
	                console.log("GradientDataColor warning:the forth key is  be force set to 1.");
	            }
	            gradientColor.addColorRGB(rgbData.key, new Color(rgbValue[0], rgbValue[1], rgbValue[2], 1.0));
	        }
	        return gradientColor;
	    }
	    _initParticleSize(gradientSizeData) {
	        var gradientSize = new GradientDataNumber();
	        var sizesData = gradientSizeData.sizes;
	        for (var i = 0, n = sizesData.length; i < n; i++) {
	            var valueData = sizesData[i];
	            gradientSize.add(valueData.key, valueData.value);
	        }
	        return gradientSize;
	    }
	    _initParticleRotation(gradientData) {
	        var gradient = new GradientDataNumber();
	        var angularVelocitysData = gradientData.angularVelocitys;
	        for (var i = 0, n = angularVelocitysData.length; i < n; i++) {
	            var valueData = angularVelocitysData[i];
	            gradient.add(valueData.key, valueData.value / 180.0 * Math.PI);
	        }
	        return gradient;
	    }
	    _initParticleFrame(overTimeFramesData) {
	        var overTimeFrame = new GradientDataInt();
	        var framesData = overTimeFramesData.frames;
	        for (var i = 0, n = framesData.length; i < n; i++) {
	            var frameData = framesData[i];
	            overTimeFrame.add(frameData.key, frameData.value);
	        }
	        return overTimeFrame;
	    }
	    _parse(data, spriteMap) {
	        super._parse(data, spriteMap);
	        const anglelToRad = Math.PI / 180.0;
	        var i, n;
	        var particleRender = this.particleRenderer;
	        var material;
	        var materialData = data.material;
	        (materialData) && (material = Laya.Loader.getRes(materialData.path));
	        particleRender.sharedMaterial = material;
	        var meshPath = data.meshPath;
	        (meshPath) && (particleRender.mesh = Laya.Loader.getRes(meshPath));
	        particleRender.renderMode = data.renderMode;
	        particleRender.stretchedBillboardCameraSpeedScale = data.stretchedBillboardCameraSpeedScale;
	        particleRender.stretchedBillboardSpeedScale = data.stretchedBillboardSpeedScale;
	        particleRender.stretchedBillboardLengthScale = data.stretchedBillboardLengthScale;
	        particleRender.sortingFudge = data.sortingFudge ? data.sortingFudge : 0.0;
	        var particleSystem = this.particleSystem;
	        particleSystem.isPerformanceMode = data.isPerformanceMode;
	        particleSystem.duration = data.duration;
	        particleSystem.looping = data.looping;
	        particleSystem.prewarm = data.prewarm;
	        particleSystem.startDelayType = data.startDelayType;
	        particleSystem.startDelay = data.startDelay;
	        particleSystem.startDelayMin = data.startDelayMin;
	        particleSystem.startDelayMax = data.startDelayMax;
	        particleSystem.startLifetimeType = data.startLifetimeType;
	        particleSystem.startLifetimeConstant = data.startLifetimeConstant;
	        particleSystem.startLifeTimeGradient = ShuriKenParticle3D._initStartLife(data.startLifetimeGradient);
	        particleSystem.startLifetimeConstantMin = data.startLifetimeConstantMin;
	        particleSystem.startLifetimeConstantMax = data.startLifetimeConstantMax;
	        particleSystem.startLifeTimeGradientMin = ShuriKenParticle3D._initStartLife(data.startLifetimeGradientMin);
	        particleSystem.startLifeTimeGradientMax = ShuriKenParticle3D._initStartLife(data.startLifetimeGradientMax);
	        particleSystem.startSpeedType = data.startSpeedType;
	        particleSystem.startSpeedConstant = data.startSpeedConstant;
	        particleSystem.startSpeedConstantMin = data.startSpeedConstantMin;
	        particleSystem.startSpeedConstantMax = data.startSpeedConstantMax;
	        particleSystem.threeDStartSize = data.threeDStartSize;
	        particleSystem.startSizeType = data.startSizeType;
	        particleSystem.startSizeConstant = data.startSizeConstant;
	        var startSizeConstantSeparateArray = data.startSizeConstantSeparate;
	        var startSizeConstantSeparateElement = particleSystem.startSizeConstantSeparate;
	        startSizeConstantSeparateElement.x = startSizeConstantSeparateArray[0];
	        startSizeConstantSeparateElement.y = startSizeConstantSeparateArray[1];
	        startSizeConstantSeparateElement.z = startSizeConstantSeparateArray[2];
	        particleSystem.startSizeConstantMin = data.startSizeConstantMin;
	        particleSystem.startSizeConstantMax = data.startSizeConstantMax;
	        var startSizeConstantMinSeparateArray = data.startSizeConstantMinSeparate;
	        var startSizeConstantMinSeparateElement = particleSystem.startSizeConstantMinSeparate;
	        startSizeConstantMinSeparateElement.x = startSizeConstantMinSeparateArray[0];
	        startSizeConstantMinSeparateElement.y = startSizeConstantMinSeparateArray[1];
	        startSizeConstantMinSeparateElement.z = startSizeConstantMinSeparateArray[2];
	        var startSizeConstantMaxSeparateArray = data.startSizeConstantMaxSeparate;
	        var startSizeConstantMaxSeparateElement = particleSystem.startSizeConstantMaxSeparate;
	        startSizeConstantMaxSeparateElement.x = startSizeConstantMaxSeparateArray[0];
	        startSizeConstantMaxSeparateElement.y = startSizeConstantMaxSeparateArray[1];
	        startSizeConstantMaxSeparateElement.z = startSizeConstantMaxSeparateArray[2];
	        particleSystem.threeDStartRotation = data.threeDStartRotation;
	        particleSystem.startRotationType = data.startRotationType;
	        particleSystem.startRotationConstant = data.startRotationConstant * anglelToRad;
	        var startRotationConstantSeparateArray = data.startRotationConstantSeparate;
	        var startRotationConstantSeparateElement = particleSystem.startRotationConstantSeparate;
	        startRotationConstantSeparateElement.x = startRotationConstantSeparateArray[0] * anglelToRad;
	        startRotationConstantSeparateElement.y = startRotationConstantSeparateArray[1] * anglelToRad;
	        startRotationConstantSeparateElement.z = startRotationConstantSeparateArray[2] * anglelToRad;
	        particleSystem.startRotationConstantMin = data.startRotationConstantMin * anglelToRad;
	        particleSystem.startRotationConstantMax = data.startRotationConstantMax * anglelToRad;
	        var startRotationConstantMinSeparateArray = data.startRotationConstantMinSeparate;
	        var startRotationConstantMinSeparateElement = particleSystem.startRotationConstantMinSeparate;
	        startRotationConstantMinSeparateElement.x = startRotationConstantMinSeparateArray[0] * anglelToRad;
	        startRotationConstantMinSeparateElement.y = startRotationConstantMinSeparateArray[1] * anglelToRad;
	        startRotationConstantMinSeparateElement.z = startRotationConstantMinSeparateArray[2] * anglelToRad;
	        var startRotationConstantMaxSeparateArray = data.startRotationConstantMaxSeparate;
	        var startRotationConstantMaxSeparateElement = particleSystem.startRotationConstantMaxSeparate;
	        startRotationConstantMaxSeparateElement.x = startRotationConstantMaxSeparateArray[0] * anglelToRad;
	        startRotationConstantMaxSeparateElement.y = startRotationConstantMaxSeparateArray[1] * anglelToRad;
	        startRotationConstantMaxSeparateElement.z = startRotationConstantMaxSeparateArray[2] * anglelToRad;
	        particleSystem.randomizeRotationDirection = data.randomizeRotationDirection;
	        particleSystem.startColorType = data.startColorType;
	        var startColorConstantArray = data.startColorConstant;
	        var startColorConstantElement = particleSystem.startColorConstant;
	        startColorConstantElement.x = startColorConstantArray[0];
	        startColorConstantElement.y = startColorConstantArray[1];
	        startColorConstantElement.z = startColorConstantArray[2];
	        startColorConstantElement.w = startColorConstantArray[3];
	        var startColorConstantMinArray = data.startColorConstantMin;
	        var startColorConstantMinElement = particleSystem.startColorConstantMin;
	        startColorConstantMinElement.x = startColorConstantMinArray[0];
	        startColorConstantMinElement.y = startColorConstantMinArray[1];
	        startColorConstantMinElement.z = startColorConstantMinArray[2];
	        startColorConstantMinElement.w = startColorConstantMinArray[3];
	        var startColorConstantMaxArray = data.startColorConstantMax;
	        var startColorConstantMaxElement = particleSystem.startColorConstantMax;
	        startColorConstantMaxElement.x = startColorConstantMaxArray[0];
	        startColorConstantMaxElement.y = startColorConstantMaxArray[1];
	        startColorConstantMaxElement.z = startColorConstantMaxArray[2];
	        startColorConstantMaxElement.w = startColorConstantMaxArray[3];
	        particleSystem.gravityModifier = data.gravityModifier;
	        particleSystem.simulationSpace = data.simulationSpace;
	        (data.simulationSpeed !== undefined) && (particleSystem.simulationSpeed = data.simulationSpeed);
	        particleSystem.scaleMode = data.scaleMode;
	        particleSystem.playOnAwake = data.playOnAwake;
	        particleSystem.maxParticles = data.maxParticles;
	        var autoRandomSeed = data.autoRandomSeed;
	        (autoRandomSeed != null) && (particleSystem.autoRandomSeed = autoRandomSeed);
	        var randomSeed = data.randomSeed;
	        (randomSeed != null) && (particleSystem.randomSeed[0] = randomSeed);
	        var emissionData = data.emission;
	        var emission = particleSystem.emission;
	        if (emissionData) {
	            emission.emissionRate = emissionData.emissionRate;
	            var burstsData = emissionData.bursts;
	            if (burstsData)
	                for (i = 0, n = burstsData.length; i < n; i++) {
	                    var brust = burstsData[i];
	                    emission.addBurst(new Burst(brust.time, brust.min, brust.max));
	                }
	            emission.enbale = emissionData.enable;
	        }
	        else {
	            emission.enbale = false;
	        }
	        var shapeData = data.shape;
	        if (shapeData) {
	            var shape;
	            switch (shapeData.shapeType) {
	                case 0:
	                    var sphereShape;
	                    shape = sphereShape = new SphereShape();
	                    sphereShape.radius = shapeData.sphereRadius;
	                    sphereShape.emitFromShell = shapeData.sphereEmitFromShell;
	                    sphereShape.randomDirection = shapeData.sphereRandomDirection;
	                    break;
	                case 1:
	                    var hemiSphereShape;
	                    shape = hemiSphereShape = new HemisphereShape();
	                    hemiSphereShape.radius = shapeData.hemiSphereRadius;
	                    hemiSphereShape.emitFromShell = shapeData.hemiSphereEmitFromShell;
	                    hemiSphereShape.randomDirection = shapeData.hemiSphereRandomDirection;
	                    break;
	                case 2:
	                    var coneShape;
	                    shape = coneShape = new ConeShape();
	                    coneShape.angle = shapeData.coneAngle * anglelToRad;
	                    coneShape.radius = shapeData.coneRadius;
	                    coneShape.length = shapeData.coneLength;
	                    coneShape.emitType = shapeData.coneEmitType;
	                    coneShape.randomDirection = shapeData.coneRandomDirection;
	                    break;
	                case 3:
	                    var boxShape;
	                    shape = boxShape = new BoxShape();
	                    boxShape.x = shapeData.boxX;
	                    boxShape.y = shapeData.boxY;
	                    boxShape.z = shapeData.boxZ;
	                    boxShape.randomDirection = shapeData.boxRandomDirection;
	                    break;
	                case 7:
	                    var circleShape;
	                    shape = circleShape = new CircleShape();
	                    circleShape.radius = shapeData.circleRadius;
	                    circleShape.arc = shapeData.circleArc * anglelToRad;
	                    circleShape.emitFromEdge = shapeData.circleEmitFromEdge;
	                    circleShape.randomDirection = shapeData.circleRandomDirection;
	                    break;
	                default:
	                    var tempShape;
	                    shape = tempShape = new CircleShape();
	                    tempShape.radius = shapeData.circleRadius;
	                    tempShape.arc = shapeData.circleArc * anglelToRad;
	                    tempShape.emitFromEdge = shapeData.circleEmitFromEdge;
	                    tempShape.randomDirection = shapeData.circleRandomDirection;
	                    break;
	            }
	            shape.enable = shapeData.enable;
	            particleSystem.shape = shape;
	        }
	        var velocityOverLifetimeData = data.velocityOverLifetime;
	        if (velocityOverLifetimeData) {
	            var velocityData = velocityOverLifetimeData.velocity;
	            var velocity;
	            switch (velocityData.type) {
	                case 0:
	                    var constantData = velocityData.constant;
	                    velocity = GradientVelocity.createByConstant(new Vector3(constantData[0], constantData[1], constantData[2]));
	                    break;
	                case 1:
	                    velocity = GradientVelocity.createByGradient(this._initParticleVelocity(velocityData.gradientX), this._initParticleVelocity(velocityData.gradientY), this._initParticleVelocity(velocityData.gradientZ));
	                    break;
	                case 2:
	                    var constantMinData = velocityData.constantMin;
	                    var constantMaxData = velocityData.constantMax;
	                    velocity = GradientVelocity.createByRandomTwoConstant(new Vector3(constantMinData[0], constantMinData[1], constantMinData[2]), new Vector3(constantMaxData[0], constantMaxData[1], constantMaxData[2]));
	                    break;
	                case 3:
	                    velocity = GradientVelocity.createByRandomTwoGradient(this._initParticleVelocity(velocityData.gradientXMin), this._initParticleVelocity(velocityData.gradientXMax), this._initParticleVelocity(velocityData.gradientYMin), this._initParticleVelocity(velocityData.gradientYMax), this._initParticleVelocity(velocityData.gradientZMin), this._initParticleVelocity(velocityData.gradientZMax));
	                    break;
	            }
	            var velocityOverLifetime = new VelocityOverLifetime(velocity);
	            velocityOverLifetime.space = velocityOverLifetimeData.space;
	            velocityOverLifetime.enbale = velocityOverLifetimeData.enable;
	            particleSystem.velocityOverLifetime = velocityOverLifetime;
	        }
	        var colorOverLifetimeData = data.colorOverLifetime;
	        if (colorOverLifetimeData) {
	            var colorData = colorOverLifetimeData.color;
	            var color;
	            switch (colorData.type) {
	                case 0:
	                    var constColorData = colorData.constant;
	                    color = GradientColor.createByConstant(new Vector4(constColorData[0], constColorData[1], constColorData[2], constColorData[3]));
	                    break;
	                case 1:
	                    color = GradientColor.createByGradient(this._initParticleColor(colorData.gradient));
	                    break;
	                case 2:
	                    var minConstColorData = colorData.constantMin;
	                    var maxConstColorData = colorData.constantMax;
	                    color = GradientColor.createByRandomTwoConstant(new Vector4(minConstColorData[0], minConstColorData[1], minConstColorData[2], minConstColorData[3]), new Vector4(maxConstColorData[0], maxConstColorData[1], maxConstColorData[2], maxConstColorData[3]));
	                    break;
	                case 3:
	                    color = GradientColor.createByRandomTwoGradient(this._initParticleColor(colorData.gradientMin), this._initParticleColor(colorData.gradientMax));
	                    break;
	            }
	            var colorOverLifetime = new ColorOverLifetime(color);
	            colorOverLifetime.enbale = colorOverLifetimeData.enable;
	            particleSystem.colorOverLifetime = colorOverLifetime;
	        }
	        var sizeOverLifetimeData = data.sizeOverLifetime;
	        if (sizeOverLifetimeData) {
	            var sizeData = sizeOverLifetimeData.size;
	            var size;
	            switch (sizeData.type) {
	                case 0:
	                    if (sizeData.separateAxes) {
	                        size = GradientSize.createByGradientSeparate(this._initParticleSize(sizeData.gradientX), this._initParticleSize(sizeData.gradientY), this._initParticleSize(sizeData.gradientZ));
	                    }
	                    else {
	                        size = GradientSize.createByGradient(this._initParticleSize(sizeData.gradient));
	                    }
	                    break;
	                case 1:
	                    if (sizeData.separateAxes) {
	                        var constantMinSeparateData = sizeData.constantMinSeparate;
	                        var constantMaxSeparateData = sizeData.constantMaxSeparate;
	                        size = GradientSize.createByRandomTwoConstantSeparate(new Vector3(constantMinSeparateData[0], constantMinSeparateData[1], constantMinSeparateData[2]), new Vector3(constantMaxSeparateData[0], constantMaxSeparateData[1], constantMaxSeparateData[2]));
	                    }
	                    else {
	                        size = GradientSize.createByRandomTwoConstant(sizeData.constantMin, sizeData.constantMax);
	                    }
	                    break;
	                case 2:
	                    if (sizeData.separateAxes) {
	                        size = GradientSize.createByRandomTwoGradientSeparate(this._initParticleSize(sizeData.gradientXMin), this._initParticleSize(sizeData.gradientYMin), this._initParticleSize(sizeData.gradientZMin), this._initParticleSize(sizeData.gradientXMax), this._initParticleSize(sizeData.gradientYMax), this._initParticleSize(sizeData.gradientZMax));
	                    }
	                    else {
	                        size = GradientSize.createByRandomTwoGradient(this._initParticleSize(sizeData.gradientMin), this._initParticleSize(sizeData.gradientMax));
	                    }
	                    break;
	            }
	            var sizeOverLifetime = new SizeOverLifetime(size);
	            sizeOverLifetime.enbale = sizeOverLifetimeData.enable;
	            particleSystem.sizeOverLifetime = sizeOverLifetime;
	        }
	        var rotationOverLifetimeData = data.rotationOverLifetime;
	        if (rotationOverLifetimeData) {
	            var angularVelocityData = rotationOverLifetimeData.angularVelocity;
	            var angularVelocity;
	            switch (angularVelocityData.type) {
	                case 0:
	                    if (angularVelocityData.separateAxes) {
	                        var conSep = angularVelocityData.constantSeparate;
	                        angularVelocity = GradientAngularVelocity.createByConstantSeparate(new Vector3(conSep[0] * anglelToRad, conSep[1] * anglelToRad, conSep[2] * anglelToRad));
	                    }
	                    else {
	                        angularVelocity = GradientAngularVelocity.createByConstant(angularVelocityData.constant * anglelToRad);
	                    }
	                    break;
	                case 1:
	                    if (angularVelocityData.separateAxes) {
	                        angularVelocity = GradientAngularVelocity.createByGradientSeparate(this._initParticleRotation(angularVelocityData.gradientX), this._initParticleRotation(angularVelocityData.gradientY), this._initParticleRotation(angularVelocityData.gradientZ));
	                    }
	                    else {
	                        angularVelocity = GradientAngularVelocity.createByGradient(this._initParticleRotation(angularVelocityData.gradient));
	                    }
	                    break;
	                case 2:
	                    if (angularVelocityData.separateAxes) {
	                        var minSep = angularVelocityData.constantMinSeparate;
	                        var maxSep = angularVelocityData.constantMaxSeparate;
	                        angularVelocity = GradientAngularVelocity.createByRandomTwoConstantSeparate(new Vector3(minSep[0] * anglelToRad, minSep[1] * anglelToRad, minSep[2] * anglelToRad), new Vector3(maxSep[0] * anglelToRad, maxSep[1] * anglelToRad, maxSep[2] * anglelToRad));
	                    }
	                    else {
	                        angularVelocity = GradientAngularVelocity.createByRandomTwoConstant(angularVelocityData.constantMin * anglelToRad, angularVelocityData.constantMax * anglelToRad);
	                    }
	                    break;
	                case 3:
	                    if (angularVelocityData.separateAxes) ;
	                    else {
	                        angularVelocity = GradientAngularVelocity.createByRandomTwoGradient(this._initParticleRotation(angularVelocityData.gradientMin), this._initParticleRotation(angularVelocityData.gradientMax));
	                    }
	                    break;
	            }
	            var rotationOverLifetime = new RotationOverLifetime(angularVelocity);
	            rotationOverLifetime.enbale = rotationOverLifetimeData.enable;
	            particleSystem.rotationOverLifetime = rotationOverLifetime;
	        }
	        var textureSheetAnimationData = data.textureSheetAnimation;
	        if (textureSheetAnimationData) {
	            var frameData = textureSheetAnimationData.frame;
	            var frameOverTime;
	            switch (frameData.type) {
	                case 0:
	                    frameOverTime = FrameOverTime.createByConstant(frameData.constant);
	                    break;
	                case 1:
	                    frameOverTime = FrameOverTime.createByOverTime(this._initParticleFrame(frameData.overTime));
	                    break;
	                case 2:
	                    frameOverTime = FrameOverTime.createByRandomTwoConstant(frameData.constantMin, frameData.constantMax);
	                    break;
	                case 3:
	                    frameOverTime = FrameOverTime.createByRandomTwoOverTime(this._initParticleFrame(frameData.overTimeMin), this._initParticleFrame(frameData.overTimeMax));
	                    break;
	            }
	            var startFrameData = textureSheetAnimationData.startFrame;
	            var startFrame;
	            switch (startFrameData.type) {
	                case 0:
	                    startFrame = StartFrame.createByConstant(startFrameData.constant);
	                    break;
	                case 1:
	                    startFrame = StartFrame.createByRandomTwoConstant(startFrameData.constantMin, startFrameData.constantMax);
	                    break;
	            }
	            var textureSheetAnimation = new TextureSheetAnimation(frameOverTime, startFrame);
	            textureSheetAnimation.enable = textureSheetAnimationData.enable;
	            var tilesData = textureSheetAnimationData.tiles;
	            textureSheetAnimation.tiles = new Vector2(tilesData[0], tilesData[1]);
	            textureSheetAnimation.type = textureSheetAnimationData.type;
	            textureSheetAnimation.randomRow = textureSheetAnimationData.randomRow;
	            var rowIndex = textureSheetAnimationData.rowIndex;
	            (rowIndex !== undefined) && (textureSheetAnimation.rowIndex = rowIndex);
	            textureSheetAnimation.cycles = textureSheetAnimationData.cycles;
	            particleSystem.textureSheetAnimation = textureSheetAnimation;
	        }
	    }
	    _activeHierarchy(activeChangeComponents) {
	        super._activeHierarchy(activeChangeComponents);
	        (this.particleSystem.playOnAwake) && (this.particleSystem.play());
	    }
	    _inActiveHierarchy(activeChangeComponents) {
	        super._inActiveHierarchy(activeChangeComponents);
	        (this.particleSystem.isAlive) && (this.particleSystem.simulate(0, true));
	    }
	    _cloneTo(destObject, srcSprite, dstSprite) {
	        var destShuriKenParticle3D = destObject;
	        var destParticleSystem = destShuriKenParticle3D._particleSystem;
	        this._particleSystem.cloneTo(destParticleSystem);
	        var destParticleRender = destShuriKenParticle3D._render;
	        var particleRender = this._render;
	        destParticleRender.sharedMaterials = particleRender.sharedMaterials;
	        destParticleRender.enable = particleRender.enable;
	        destParticleRender.renderMode = particleRender.renderMode;
	        destParticleRender.mesh = particleRender.mesh;
	        destParticleRender.stretchedBillboardCameraSpeedScale = particleRender.stretchedBillboardCameraSpeedScale;
	        destParticleRender.stretchedBillboardSpeedScale = particleRender.stretchedBillboardSpeedScale;
	        destParticleRender.stretchedBillboardLengthScale = particleRender.stretchedBillboardLengthScale;
	        destParticleRender.sortingFudge = particleRender.sortingFudge;
	        super._cloneTo(destObject, srcSprite, dstSprite);
	    }
	    destroy(destroyChild = true) {
	        if (this.destroyed)
	            return;
	        super.destroy(destroyChild);
	        this._particleSystem.destroy();
	        this._particleSystem = null;
	    }
	    _create() {
	        return new ShuriKenParticle3D();
	    }
	}

	class PixelLineMaterial extends BaseMaterial {
	    constructor() {
	        super();
	        this.setShaderName("LineShader");
	        this._shaderValues.setVector(PixelLineMaterial.COLOR, new Vector4(1.0, 1.0, 1.0, 1.0));
	    }
	    static __initDefine__() {
	    }
	    get color() {
	        return this._shaderValues.getVector(PixelLineMaterial.COLOR);
	    }
	    set color(value) {
	        this._shaderValues.setVector(PixelLineMaterial.COLOR, value);
	    }
	    set depthWrite(value) {
	        this._shaderValues.setBool(PixelLineMaterial.DEPTH_WRITE, value);
	    }
	    get depthWrite() {
	        return this._shaderValues.getBool(PixelLineMaterial.DEPTH_WRITE);
	    }
	    set cull(value) {
	        this._shaderValues.setInt(PixelLineMaterial.CULL, value);
	    }
	    get cull() {
	        return this._shaderValues.getInt(PixelLineMaterial.CULL);
	    }
	    set blend(value) {
	        this._shaderValues.setInt(PixelLineMaterial.BLEND, value);
	    }
	    get blend() {
	        return this._shaderValues.getInt(PixelLineMaterial.BLEND);
	    }
	    set blendSrc(value) {
	        this._shaderValues.setInt(PixelLineMaterial.BLEND_SRC, value);
	    }
	    get blendSrc() {
	        return this._shaderValues.getInt(PixelLineMaterial.BLEND_SRC);
	    }
	    set blendDst(value) {
	        this._shaderValues.setInt(PixelLineMaterial.BLEND_DST, value);
	    }
	    get blendDst() {
	        return this._shaderValues.getInt(PixelLineMaterial.BLEND_DST);
	    }
	    set depthTest(value) {
	        this._shaderValues.setInt(PixelLineMaterial.DEPTH_TEST, value);
	    }
	    get depthTest() {
	        return this._shaderValues.getInt(PixelLineMaterial.DEPTH_TEST);
	    }
	    clone() {
	        var dest = new PixelLineMaterial();
	        this.cloneTo(dest);
	        return dest;
	    }
	}
	PixelLineMaterial.COLOR = Shader3D.propertyNameToID("u_Color");
	PixelLineMaterial.CULL = Shader3D.propertyNameToID("s_Cull");
	PixelLineMaterial.BLEND = Shader3D.propertyNameToID("s_Blend");
	PixelLineMaterial.BLEND_SRC = Shader3D.propertyNameToID("s_BlendSrc");
	PixelLineMaterial.BLEND_DST = Shader3D.propertyNameToID("s_BlendDst");
	PixelLineMaterial.DEPTH_TEST = Shader3D.propertyNameToID("s_DepthTest");
	PixelLineMaterial.DEPTH_WRITE = Shader3D.propertyNameToID("s_DepthWrite");

	class PixelLineVertex {
	    static get vertexDeclaration() {
	        return PixelLineVertex._vertexDeclaration;
	    }
	    static __init__() {
	        PixelLineVertex._vertexDeclaration = new VertexDeclaration(28, [new VertexElement(0, VertexElementFormat.Vector3, VertexMesh.MESH_POSITION0),
	            new VertexElement(12, VertexElementFormat.Vector4, VertexMesh.MESH_COLOR0)]);
	    }
	    get vertexDeclaration() {
	        return PixelLineVertex._vertexDeclaration;
	    }
	    constructor() {
	    }
	}

	class CastShadowList extends SingletonList {
	    constructor() {
	        super();
	    }
	    add(element) {
	        var index = element._indexInCastShadowList;
	        if (index !== -1)
	            throw "CastShadowList:element has  in  CastShadowList.";
	        this._add(element);
	        element._indexInCastShadowList = this.length++;
	    }
	    remove(element) {
	        var index = element._indexInCastShadowList;
	        this.length--;
	        if (index !== this.length) {
	            var end = this.elements[this.length];
	            this.elements[index] = end;
	            end._indexInCastShadowList = index;
	        }
	        element._indexInCastShadowList = -1;
	    }
	}

	class SimpleSingletonList extends SingletonList {
	    constructor() {
	        super();
	    }
	    add(element) {
	        var index = element._getIndexInList();
	        if (index !== -1)
	            throw "SimpleSingletonList:" + element + " has  in  SingletonList.";
	        this._add(element);
	        element._setIndexInList(this.length++);
	    }
	    remove(element) {
	        var index = element._getIndexInList();
	        this.length--;
	        if (index !== this.length) {
	            var end = this.elements[this.length];
	            this.elements[index] = end;
	            end._setIndexInList(index);
	        }
	        element._setIndexInList(-1);
	    }
	}

	class MouseTouch {
	    constructor() {
	        this._pressedSprite = null;
	        this._pressedLoopCount = -1;
	        this.sprite = null;
	        this.mousePositionX = 0;
	        this.mousePositionY = 0;
	    }
	}

	class Touch {
	    constructor() {
	        this._indexInList = -1;
	        this._identifier = -1;
	        this._position = new Vector2();
	    }
	    get identifier() {
	        return this._identifier;
	    }
	    get position() {
	        return this._position;
	    }
	    _getIndexInList() {
	        return this._indexInList;
	    }
	    _setIndexInList(index) {
	        this._indexInList = index;
	    }
	}

	class HitResult {
	    constructor() {
	        this.succeeded = false;
	        this.collider = null;
	        this.point = new Vector3();
	        this.normal = new Vector3();
	        this.hitFraction = 0;
	    }
	}

	class PhysicsUpdateList extends SingletonList {
	    constructor() {
	        super();
	    }
	    add(element) {
	        var index = element._inPhysicUpdateListIndex;
	        if (index !== -1)
	            throw "PhysicsUpdateList:element has  in  PhysicsUpdateList.";
	        this._add(element);
	        element._inPhysicUpdateListIndex = this.length++;
	    }
	    remove(element) {
	        var index = element._inPhysicUpdateListIndex;
	        this.length--;
	        if (index !== this.length) {
	            var end = this.elements[this.length];
	            this.elements[index] = end;
	            end._inPhysicUpdateListIndex = index;
	        }
	        element._inPhysicUpdateListIndex = -1;
	    }
	}

	class ContactPoint {
	    constructor() {
	        this._idCounter = 0;
	        this.colliderA = null;
	        this.colliderB = null;
	        this.distance = 0;
	        this.normal = new Vector3();
	        this.positionOnA = new Vector3();
	        this.positionOnB = new Vector3();
	        this._id = ++this._idCounter;
	    }
	}

	class Collision {
	    constructor() {
	        this._lastUpdateFrame = -2147483648;
	        this._updateFrame = -2147483648;
	        this._isTrigger = false;
	        this.contacts = [];
	    }
	    _setUpdateFrame(farme) {
	        this._lastUpdateFrame = this._updateFrame;
	        this._updateFrame = farme;
	    }
	}

	class CollisionTool {
	    constructor() {
	        this._hitResultsPoolIndex = 0;
	        this._hitResultsPool = [];
	        this._contactPonintsPoolIndex = 0;
	        this._contactPointsPool = [];
	        this._collisionsPool = [];
	        this._collisions = {};
	    }
	    getHitResult() {
	        var hitResult = this._hitResultsPool[this._hitResultsPoolIndex++];
	        if (!hitResult) {
	            hitResult = new HitResult();
	            this._hitResultsPool.push(hitResult);
	        }
	        return hitResult;
	    }
	    recoverAllHitResultsPool() {
	        this._hitResultsPoolIndex = 0;
	    }
	    getContactPoints() {
	        var contactPoint = this._contactPointsPool[this._contactPonintsPoolIndex++];
	        if (!contactPoint) {
	            contactPoint = new ContactPoint();
	            this._contactPointsPool.push(contactPoint);
	        }
	        return contactPoint;
	    }
	    recoverAllContactPointsPool() {
	        this._contactPonintsPoolIndex = 0;
	    }
	    getCollision(physicComponentA, physicComponentB) {
	        var collision;
	        var idA = physicComponentA.id;
	        var idB = physicComponentB.id;
	        var subCollisionFirst = this._collisions[idA];
	        if (subCollisionFirst)
	            collision = subCollisionFirst[idB];
	        if (!collision) {
	            if (!subCollisionFirst) {
	                subCollisionFirst = {};
	                this._collisions[idA] = subCollisionFirst;
	            }
	            collision = this._collisionsPool.length === 0 ? new Collision() : this._collisionsPool.pop();
	            collision._colliderA = physicComponentA;
	            collision._colliderB = physicComponentB;
	            subCollisionFirst[idB] = collision;
	        }
	        return collision;
	    }
	    recoverCollision(collision) {
	        var idA = collision._colliderA.id;
	        var idB = collision._colliderB.id;
	        this._collisions[idA][idB] = null;
	        this._collisionsPool.push(collision);
	    }
	    garbageCollection() {
	        this._hitResultsPoolIndex = 0;
	        this._hitResultsPool.length = 0;
	        this._contactPonintsPoolIndex = 0;
	        this._contactPointsPool.length = 0;
	        this._collisionsPool.length = 0;
	        for (var subCollisionsKey in this._collisionsPool) {
	            var subCollisions = this._collisionsPool[subCollisionsKey];
	            var wholeDelete = true;
	            for (var collisionKey in subCollisions) {
	                if (subCollisions[collisionKey])
	                    wholeDelete = false;
	                else
	                    delete subCollisions[collisionKey];
	            }
	            if (wholeDelete)
	                delete this._collisionsPool[subCollisionsKey];
	        }
	    }
	}

	class Physics3D {
	}
	Physics3D._physics3D = null;
	Physics3D._enbalePhysics = false;

	class ColliderShape {
	    constructor() {
	        this._scale = new Vector3(1, 1, 1);
	        this._centerMatrix = new Matrix4x4();
	        this._attatched = false;
	        this._indexInCompound = -1;
	        this._compoundParent = null;
	        this._attatchedCollisionObject = null;
	        this._referenceCount = 0;
	        this._localOffset = new Vector3(0, 0, 0);
	        this._localRotation = new Quaternion(0, 0, 0, 1);
	        this.needsCustomCollisionCallback = false;
	    }
	    static __init__() {
	        ColliderShape._nativeScale = new Physics3D._physics3D.btVector3(1, 1, 1);
	        ColliderShape._nativeVector30 = new Physics3D._physics3D.btVector3(0, 0, 0);
	        ColliderShape._nativQuaternion0 = new Physics3D._physics3D.btQuaternion(0, 0, 0, 1);
	        ColliderShape._nativeTransform0 = new Physics3D._physics3D.btTransform();
	    }
	    static _createAffineTransformation(trans, rot, outE) {
	        var x = rot.x, y = rot.y, z = rot.z, w = rot.w, x2 = x + x, y2 = y + y, z2 = z + z;
	        var xx = x * x2, xy = x * y2, xz = x * z2, yy = y * y2, yz = y * z2, zz = z * z2;
	        var wx = w * x2, wy = w * y2, wz = w * z2;
	        outE[0] = (1 - (yy + zz));
	        outE[1] = (xy + wz);
	        outE[2] = (xz - wy);
	        outE[3] = 0;
	        outE[4] = (xy - wz);
	        outE[5] = (1 - (xx + zz));
	        outE[6] = (yz + wx);
	        outE[7] = 0;
	        outE[8] = (xz + wy);
	        outE[9] = (yz - wx);
	        outE[10] = (1 - (xx + yy));
	        outE[11] = 0;
	        outE[12] = trans.x;
	        outE[13] = trans.y;
	        outE[14] = trans.z;
	        outE[15] = 1;
	    }
	    get type() {
	        return this._type;
	    }
	    get localOffset() {
	        return this._localOffset;
	    }
	    set localOffset(value) {
	        this._localOffset = value;
	        if (this._compoundParent)
	            this._compoundParent._updateChildTransform(this);
	    }
	    get localRotation() {
	        return this._localRotation;
	    }
	    set localRotation(value) {
	        this._localRotation = value;
	        if (this._compoundParent)
	            this._compoundParent._updateChildTransform(this);
	    }
	    _setScale(value) {
	        if (this._compoundParent) {
	            this.updateLocalTransformations();
	        }
	        else {
	            ColliderShape._nativeScale.setValue(value.x, value.y, value.z);
	            this._nativeShape.setLocalScaling(ColliderShape._nativeScale);
	        }
	    }
	    _addReference() {
	        this._referenceCount++;
	    }
	    _removeReference() {
	        this._referenceCount--;
	    }
	    updateLocalTransformations() {
	        if (this._compoundParent) {
	            var offset = ColliderShape._tempVector30;
	            Vector3.multiply(this.localOffset, this._scale, offset);
	            ColliderShape._createAffineTransformation(offset, this.localRotation, this._centerMatrix.elements);
	        }
	        else {
	            ColliderShape._createAffineTransformation(this.localOffset, this.localRotation, this._centerMatrix.elements);
	        }
	    }
	    cloneTo(destObject) {
	        var destColliderShape = destObject;
	        this._localOffset.cloneTo(destColliderShape.localOffset);
	        this._localRotation.cloneTo(destColliderShape.localRotation);
	        destColliderShape.localOffset = destColliderShape.localOffset;
	        destColliderShape.localRotation = destColliderShape.localRotation;
	    }
	    clone() {
	        return null;
	    }
	    destroy() {
	        if (this._nativeShape) {
	            Physics3D._physics3D.destroy(this._nativeShape);
	            this._nativeShape = null;
	        }
	    }
	}
	ColliderShape.SHAPEORIENTATION_UPX = 0;
	ColliderShape.SHAPEORIENTATION_UPY = 1;
	ColliderShape.SHAPEORIENTATION_UPZ = 2;
	ColliderShape.SHAPETYPES_BOX = 0;
	ColliderShape.SHAPETYPES_SPHERE = 1;
	ColliderShape.SHAPETYPES_CYLINDER = 2;
	ColliderShape.SHAPETYPES_CAPSULE = 3;
	ColliderShape.SHAPETYPES_CONVEXHULL = 4;
	ColliderShape.SHAPETYPES_COMPOUND = 5;
	ColliderShape.SHAPETYPES_STATICPLANE = 6;
	ColliderShape.SHAPETYPES_CONE = 7;
	ColliderShape._tempVector30 = new Vector3();

	class BoxColliderShape extends ColliderShape {
	    static __init__() {
	        BoxColliderShape._nativeSize = new Physics3D._physics3D.btVector3(0, 0, 0);
	    }
	    get sizeX() {
	        return this._sizeX;
	    }
	    get sizeY() {
	        return this._sizeY;
	    }
	    get sizeZ() {
	        return this._sizeZ;
	    }
	    constructor(sizeX = 1.0, sizeY = 1.0, sizeZ = 1.0) {
	        super();
	        this._sizeX = sizeX;
	        this._sizeY = sizeY;
	        this._sizeZ = sizeZ;
	        this._type = ColliderShape.SHAPETYPES_BOX;
	        BoxColliderShape._nativeSize.setValue(sizeX / 2, sizeY / 2, sizeZ / 2);
	        this._nativeShape = new Physics3D._physics3D.btBoxShape(BoxColliderShape._nativeSize);
	    }
	    clone() {
	        var dest = new BoxColliderShape(this._sizeX, this._sizeY, this._sizeZ);
	        this.cloneTo(dest);
	        return dest;
	    }
	}

	class CapsuleColliderShape extends ColliderShape {
	    constructor(radius = 0.5, length = 1.25, orientation = ColliderShape.SHAPEORIENTATION_UPY) {
	        super();
	        this._radius = radius;
	        this._length = length;
	        this._orientation = orientation;
	        this._type = ColliderShape.SHAPETYPES_CAPSULE;
	        switch (orientation) {
	            case ColliderShape.SHAPEORIENTATION_UPX:
	                this._nativeShape = new Physics3D._physics3D.btCapsuleShapeX(radius, length - radius * 2);
	                break;
	            case ColliderShape.SHAPEORIENTATION_UPY:
	                this._nativeShape = new Physics3D._physics3D.btCapsuleShape(radius, length - radius * 2);
	                break;
	            case ColliderShape.SHAPEORIENTATION_UPZ:
	                this._nativeShape = new Physics3D._physics3D.btCapsuleShapeZ(radius, length - radius * 2);
	                break;
	            default:
	                throw "CapsuleColliderShape:unknown orientation.";
	        }
	    }
	    get radius() {
	        return this._radius;
	    }
	    get length() {
	        return this._length;
	    }
	    get orientation() {
	        return this._orientation;
	    }
	    _setScale(value) {
	        var fixScale = CapsuleColliderShape._tempVector30;
	        switch (this.orientation) {
	            case ColliderShape.SHAPEORIENTATION_UPX:
	                fixScale.x = value.x;
	                fixScale.y = fixScale.z = Math.max(value.y, value.z);
	                break;
	            case ColliderShape.SHAPEORIENTATION_UPY:
	                fixScale.y = value.y;
	                fixScale.x = fixScale.z = Math.max(value.x, value.z);
	                break;
	            case ColliderShape.SHAPEORIENTATION_UPZ:
	                fixScale.z = value.z;
	                fixScale.x = fixScale.y = Math.max(value.x, value.y);
	                break;
	            default:
	                throw "CapsuleColliderShape:unknown orientation.";
	        }
	        super._setScale(fixScale);
	    }
	    clone() {
	        var dest = new CapsuleColliderShape(this._radius, this._length, this._orientation);
	        this.cloneTo(dest);
	        return dest;
	    }
	}
	CapsuleColliderShape._tempVector30 = new Vector3();

	class CompoundColliderShape extends ColliderShape {
	    constructor() {
	        super();
	        this._childColliderShapes = [];
	        this._type = ColliderShape.SHAPETYPES_COMPOUND;
	        this._nativeShape = new Physics3D._physics3D.btCompoundShape();
	    }
	    static __init__() {
	        CompoundColliderShape._nativeVector3One = new Physics3D._physics3D.btVector3(1, 1, 1);
	        CompoundColliderShape._nativeTransform = new Physics3D._physics3D.btTransform();
	        CompoundColliderShape._nativeOffset = new Physics3D._physics3D.btVector3(0, 0, 0);
	        CompoundColliderShape._nativRotation = new Physics3D._physics3D.btQuaternion(0, 0, 0, 1);
	    }
	    _clearChildShape(shape) {
	        shape._attatched = false;
	        shape._compoundParent = null;
	        shape._indexInCompound = -1;
	    }
	    _addReference() {
	    }
	    _removeReference() {
	    }
	    _updateChildTransform(shape) {
	        var offset = shape.localOffset;
	        var rotation = shape.localRotation;
	        var nativeOffset = ColliderShape._nativeVector30;
	        var nativeQuaternion = ColliderShape._nativQuaternion0;
	        var nativeTransform = ColliderShape._nativeTransform0;
	        nativeOffset.setValue(-offset.x, offset.y, offset.z);
	        nativeQuaternion.setValue(-rotation.x, rotation.y, rotation.z, -rotation.w);
	        nativeTransform.setOrigin(nativeOffset);
	        nativeTransform.setRotation(nativeQuaternion);
	        this._nativeShape.updateChildTransform(shape._indexInCompound, nativeTransform, true);
	    }
	    addChildShape(shape) {
	        if (shape._attatched)
	            throw "CompoundColliderShape: this shape has attatched to other entity.";
	        shape._attatched = true;
	        shape._compoundParent = this;
	        shape._indexInCompound = this._childColliderShapes.length;
	        this._childColliderShapes.push(shape);
	        var offset = shape.localOffset;
	        var rotation = shape.localRotation;
	        CompoundColliderShape._nativeOffset.setValue(-offset.x, offset.y, offset.z);
	        CompoundColliderShape._nativRotation.setValue(-rotation.x, rotation.y, rotation.z, -rotation.w);
	        CompoundColliderShape._nativeTransform.setOrigin(CompoundColliderShape._nativeOffset);
	        CompoundColliderShape._nativeTransform.setRotation(CompoundColliderShape._nativRotation);
	        var nativeScale = this._nativeShape.getLocalScaling();
	        this._nativeShape.setLocalScaling(CompoundColliderShape._nativeVector3One);
	        this._nativeShape.addChildShape(CompoundColliderShape._nativeTransform, shape._nativeShape);
	        this._nativeShape.setLocalScaling(nativeScale);
	        (this._attatchedCollisionObject) && (this._attatchedCollisionObject.colliderShape = this);
	    }
	    removeChildShape(shape) {
	        if (shape._compoundParent === this) {
	            var index = shape._indexInCompound;
	            this._clearChildShape(shape);
	            var endShape = this._childColliderShapes[this._childColliderShapes.length - 1];
	            endShape._indexInCompound = index;
	            this._childColliderShapes[index] = endShape;
	            this._childColliderShapes.pop();
	            this._nativeShape.removeChildShapeByIndex(index);
	        }
	    }
	    clearChildShape() {
	        for (var i = 0, n = this._childColliderShapes.length; i < n; i++) {
	            this._clearChildShape(this._childColliderShapes[i]);
	            this._nativeShape.removeChildShapeByIndex(0);
	        }
	        this._childColliderShapes.length = 0;
	    }
	    getChildShapeCount() {
	        return this._childColliderShapes.length;
	    }
	    cloneTo(destObject) {
	        var destCompoundColliderShape = destObject;
	        destCompoundColliderShape.clearChildShape();
	        for (var i = 0, n = this._childColliderShapes.length; i < n; i++)
	            destCompoundColliderShape.addChildShape(this._childColliderShapes[i].clone());
	    }
	    clone() {
	        var dest = new CompoundColliderShape();
	        this.cloneTo(dest);
	        return dest;
	    }
	    destroy() {
	        super.destroy();
	        for (var i = 0, n = this._childColliderShapes.length; i < n; i++) {
	            var childShape = this._childColliderShapes[i];
	            if (childShape._referenceCount === 0)
	                childShape.destroy();
	        }
	    }
	}

	class ConeColliderShape extends ColliderShape {
	    constructor(radius = 0.5, height = 1.0, orientation = ColliderShape.SHAPEORIENTATION_UPY) {
	        super();
	        this._radius = 1;
	        this._height = 0.5;
	        this._radius = radius;
	        this._height = height;
	        this._orientation = orientation;
	        this._type = ColliderShape.SHAPETYPES_CYLINDER;
	        switch (orientation) {
	            case ColliderShape.SHAPEORIENTATION_UPX:
	                this._nativeShape = new Physics3D._physics3D.btConeShapeX(radius, height);
	                break;
	            case ColliderShape.SHAPEORIENTATION_UPY:
	                this._nativeShape = new Physics3D._physics3D.btConeShape(radius, height);
	                break;
	            case ColliderShape.SHAPEORIENTATION_UPZ:
	                this._nativeShape = new Physics3D._physics3D.btConeShapeZ(radius, height);
	                break;
	            default:
	                throw "ConeColliderShape:unknown orientation.";
	        }
	    }
	    get radius() {
	        return this._radius;
	    }
	    get height() {
	        return this._height;
	    }
	    get orientation() {
	        return this._orientation;
	    }
	    clone() {
	        var dest = new ConeColliderShape(this._radius, this._height, this._orientation);
	        this.cloneTo(dest);
	        return dest;
	    }
	}

	class CylinderColliderShape extends ColliderShape {
	    constructor(radius = 0.5, height = 1.0, orientation = ColliderShape.SHAPEORIENTATION_UPY) {
	        super();
	        this._radius = 1;
	        this._height = 0.5;
	        this._radius = radius;
	        this._height = height;
	        this._orientation = orientation;
	        this._type = ColliderShape.SHAPETYPES_CYLINDER;
	        switch (orientation) {
	            case ColliderShape.SHAPEORIENTATION_UPX:
	                CylinderColliderShape._nativeSize.setValue(height / 2, radius, radius);
	                this._nativeShape = new Physics3D._physics3D.btCylinderShapeX(CylinderColliderShape._nativeSize);
	                break;
	            case ColliderShape.SHAPEORIENTATION_UPY:
	                CylinderColliderShape._nativeSize.setValue(radius, height / 2, radius);
	                this._nativeShape = new Physics3D._physics3D.btCylinderShape(CylinderColliderShape._nativeSize);
	                break;
	            case ColliderShape.SHAPEORIENTATION_UPZ:
	                CylinderColliderShape._nativeSize.setValue(radius, radius, height / 2);
	                this._nativeShape = new Physics3D._physics3D.btCylinderShapeZ(CylinderColliderShape._nativeSize);
	                break;
	            default:
	                throw "CapsuleColliderShape:unknown orientation.";
	        }
	    }
	    static __init__() {
	        CylinderColliderShape._nativeSize = new Physics3D._physics3D.btVector3(0, 0, 0);
	    }
	    get radius() {
	        return this._radius;
	    }
	    get height() {
	        return this._height;
	    }
	    get orientation() {
	        return this._orientation;
	    }
	    clone() {
	        var dest = new CylinderColliderShape(this._radius, this._height, this._orientation);
	        this.cloneTo(dest);
	        return dest;
	    }
	}

	class MeshColliderShape extends ColliderShape {
	    constructor() {
	        super();
	        this._mesh = null;
	        this._convex = false;
	    }
	    get mesh() {
	        return this._mesh;
	    }
	    set mesh(value) {
	        if (this._mesh !== value) {
	            var physics3D = Physics3D._physics3D;
	            if (this._mesh) {
	                physics3D.destroy(this._nativeShape);
	            }
	            if (value) {
	                this._nativeShape = new Physics3D._physics3D.btGImpactMeshShape(value._getPhysicMesh());
	                this._nativeShape.updateBound();
	            }
	            this._mesh = value;
	        }
	    }
	    get convex() {
	        return this._convex;
	    }
	    set convex(value) {
	        this._convex = value;
	    }
	    _setScale(value) {
	        if (this._compoundParent) {
	            this.updateLocalTransformations();
	        }
	        else {
	            ColliderShape._nativeScale.setValue(value.x, value.y, value.z);
	            this._nativeShape.setLocalScaling(ColliderShape._nativeScale);
	            this._nativeShape.updateBound();
	        }
	    }
	    cloneTo(destObject) {
	        var destMeshCollider = destObject;
	        destMeshCollider.convex = this._convex;
	        destMeshCollider.mesh = this._mesh;
	        super.cloneTo(destObject);
	    }
	    clone() {
	        var dest = new MeshColliderShape();
	        this.cloneTo(dest);
	        return dest;
	    }
	    destroy() {
	        if (this._nativeShape) {
	            var physics3D = Physics3D._physics3D;
	            physics3D.destroy(this._nativeShape);
	            this._nativeShape = null;
	        }
	    }
	}

	class SphereColliderShape extends ColliderShape {
	    get radius() {
	        return this._radius;
	    }
	    constructor(radius = 0.5) {
	        super();
	        this._radius = radius;
	        this._type = ColliderShape.SHAPETYPES_SPHERE;
	        this._nativeShape = new Physics3D._physics3D.btSphereShape(radius);
	    }
	    clone() {
	        var dest = new SphereColliderShape(this._radius);
	        this.cloneTo(dest);
	        return dest;
	    }
	}

	class PhysicsComponent extends Laya.Component {
	    constructor(collisionGroup, canCollideWith) {
	        super();
	        this._restitution = 0.0;
	        this._friction = 0.5;
	        this._rollingFriction = 0.0;
	        this._ccdMotionThreshold = 0.0;
	        this._ccdSweptSphereRadius = 0.0;
	        this._collisionGroup = Physics3DUtils.COLLISIONFILTERGROUP_DEFAULTFILTER;
	        this._canCollideWith = Physics3DUtils.COLLISIONFILTERGROUP_ALLFILTER;
	        this._colliderShape = null;
	        this._transformFlag = 2147483647;
	        this._enableProcessCollisions = true;
	        this._inPhysicUpdateListIndex = -1;
	        this.canScaleShape = true;
	        this._collisionGroup = collisionGroup;
	        this._canCollideWith = canCollideWith;
	        PhysicsComponent._physicObjectsMap[this.id] = this;
	    }
	    static __init__() {
	        PhysicsComponent._nativeVector30 = new Physics3D._physics3D.btVector3(0, 0, 0);
	        PhysicsComponent._nativeQuaternion0 = new Physics3D._physics3D.btQuaternion(0, 0, 0, 1);
	    }
	    static _createAffineTransformationArray(tranX, tranY, tranZ, rotX, rotY, rotZ, rotW, scale, outE) {
	        var x2 = rotX + rotX, y2 = rotY + rotY, z2 = rotZ + rotZ;
	        var xx = rotX * x2, xy = rotX * y2, xz = rotX * z2, yy = rotY * y2, yz = rotY * z2, zz = rotZ * z2;
	        var wx = rotW * x2, wy = rotW * y2, wz = rotW * z2, sx = scale[0], sy = scale[1], sz = scale[2];
	        outE[0] = (1 - (yy + zz)) * sx;
	        outE[1] = (xy + wz) * sx;
	        outE[2] = (xz - wy) * sx;
	        outE[3] = 0;
	        outE[4] = (xy - wz) * sy;
	        outE[5] = (1 - (xx + zz)) * sy;
	        outE[6] = (yz + wx) * sy;
	        outE[7] = 0;
	        outE[8] = (xz + wy) * sz;
	        outE[9] = (yz - wx) * sz;
	        outE[10] = (1 - (xx + yy)) * sz;
	        outE[11] = 0;
	        outE[12] = tranX;
	        outE[13] = tranY;
	        outE[14] = tranZ;
	        outE[15] = 1;
	    }
	    static _creatShape(shapeData) {
	        var colliderShape;
	        switch (shapeData.type) {
	            case "BoxColliderShape":
	                var sizeData = shapeData.size;
	                colliderShape = sizeData ? new BoxColliderShape(sizeData[0], sizeData[1], sizeData[2]) : new BoxColliderShape();
	                break;
	            case "SphereColliderShape":
	                colliderShape = new SphereColliderShape(shapeData.radius);
	                break;
	            case "CapsuleColliderShape":
	                colliderShape = new CapsuleColliderShape(shapeData.radius, shapeData.height, shapeData.orientation);
	                break;
	            case "MeshColliderShape":
	                var meshCollider = new MeshColliderShape();
	                shapeData.mesh && (meshCollider.mesh = Laya.Loader.getRes(shapeData.mesh));
	                colliderShape = meshCollider;
	                break;
	            case "ConeColliderShape":
	                colliderShape = new ConeColliderShape(shapeData.radius, shapeData.height, shapeData.orientation);
	                break;
	            case "CylinderColliderShape":
	                colliderShape = new CylinderColliderShape(shapeData.radius, shapeData.height, shapeData.orientation);
	                break;
	            default:
	                throw "unknown shape type.";
	        }
	        if (shapeData.center) {
	            var localOffset = colliderShape.localOffset;
	            localOffset.fromArray(shapeData.center);
	            colliderShape.localOffset = localOffset;
	        }
	        return colliderShape;
	    }
	    static physicVector3TransformQuat(source, qx, qy, qz, qw, out) {
	        var x = source.x, y = source.y, z = source.z, ix = qw * x + qy * z - qz * y, iy = qw * y + qz * x - qx * z, iz = qw * z + qx * y - qy * x, iw = -qx * x - qy * y - qz * z;
	        out.x = ix * qw + iw * -qx + iy * -qz - iz * -qy;
	        out.y = iy * qw + iw * -qy + iz * -qx - ix * -qz;
	        out.z = iz * qw + iw * -qz + ix * -qy - iy * -qx;
	    }
	    static physicQuaternionMultiply(lx, ly, lz, lw, right, out) {
	        var rx = right.x;
	        var ry = right.y;
	        var rz = right.z;
	        var rw = right.w;
	        var a = (ly * rz - lz * ry);
	        var b = (lz * rx - lx * rz);
	        var c = (lx * ry - ly * rx);
	        var d = (lx * rx + ly * ry + lz * rz);
	        out.x = (lx * rw + rx * lw) + a;
	        out.y = (ly * rw + ry * lw) + b;
	        out.z = (lz * rw + rz * lw) + c;
	        out.w = lw * rw - d;
	    }
	    get restitution() {
	        return this._restitution;
	    }
	    set restitution(value) {
	        this._restitution = value;
	        this._nativeColliderObject && this._nativeColliderObject.setRestitution(value);
	    }
	    get friction() {
	        return this._friction;
	    }
	    set friction(value) {
	        this._friction = value;
	        this._nativeColliderObject && this._nativeColliderObject.setFriction(value);
	    }
	    get rollingFriction() {
	        return this._nativeColliderObject.getRollingFriction();
	    }
	    set rollingFriction(value) {
	        this._rollingFriction = value;
	        this._nativeColliderObject && this._nativeColliderObject.setRollingFriction(value);
	    }
	    get ccdMotionThreshold() {
	        return this._ccdMotionThreshold;
	    }
	    set ccdMotionThreshold(value) {
	        this._ccdMotionThreshold = value;
	        this._nativeColliderObject && this._nativeColliderObject.setCcdMotionThreshold(value);
	    }
	    get ccdSweptSphereRadius() {
	        return this._ccdSweptSphereRadius;
	    }
	    set ccdSweptSphereRadius(value) {
	        this._ccdSweptSphereRadius = value;
	        this._nativeColliderObject && this._nativeColliderObject.setCcdSweptSphereRadius(value);
	    }
	    get isActive() {
	        return this._nativeColliderObject ? this._nativeColliderObject.isActive() : false;
	    }
	    get enabled() {
	        return super.enabled;
	    }
	    set enabled(value) {
	        if (this._enabled != value) {
	            if (this._simulation && this._colliderShape) {
	                if (value) {
	                    this._derivePhysicsTransformation(true);
	                    this._addToSimulation();
	                }
	                else {
	                    this._removeFromSimulation();
	                }
	            }
	            super.enabled = value;
	        }
	    }
	    get colliderShape() {
	        return this._colliderShape;
	    }
	    set colliderShape(value) {
	        var lastColliderShape = this._colliderShape;
	        if (lastColliderShape) {
	            lastColliderShape._attatched = false;
	            lastColliderShape._attatchedCollisionObject = null;
	        }
	        this._colliderShape = value;
	        if (value) {
	            if (value._attatched) {
	                throw "PhysicsComponent: this shape has attatched to other entity.";
	            }
	            else {
	                value._attatched = true;
	                value._attatchedCollisionObject = this;
	            }
	            if (this._nativeColliderObject) {
	                this._nativeColliderObject.setCollisionShape(value._nativeShape);
	                var canInSimulation = this._simulation && this._enabled;
	                (canInSimulation && lastColliderShape) && (this._removeFromSimulation());
	                this._onShapeChange(value);
	                if (canInSimulation) {
	                    this._derivePhysicsTransformation(true);
	                    this._addToSimulation();
	                }
	            }
	        }
	        else {
	            if (this._simulation && this._enabled)
	                lastColliderShape && this._removeFromSimulation();
	        }
	    }
	    get simulation() {
	        return this._simulation;
	    }
	    get collisionGroup() {
	        return this._collisionGroup;
	    }
	    set collisionGroup(value) {
	        if (this._collisionGroup !== value) {
	            this._collisionGroup = value;
	            if (this._simulation && this._colliderShape && this._enabled) {
	                this._removeFromSimulation();
	                this._addToSimulation();
	            }
	        }
	    }
	    get canCollideWith() {
	        return this._canCollideWith;
	    }
	    set canCollideWith(value) {
	        if (this._canCollideWith !== value) {
	            this._canCollideWith = value;
	            if (this._simulation && this._colliderShape && this._enabled) {
	                this._removeFromSimulation();
	                this._addToSimulation();
	            }
	        }
	    }
	    _isValid() {
	        return this._simulation && this._colliderShape && this._enabled;
	    }
	    _parse(data) {
	        (data.collisionGroup != null) && (this.collisionGroup = data.collisionGroup);
	        (data.canCollideWith != null) && (this.canCollideWith = data.canCollideWith);
	        (data.ccdMotionThreshold != null) && (this.ccdMotionThreshold = data.ccdMotionThreshold);
	        (data.ccdSweptSphereRadius != null) && (this.ccdSweptSphereRadius = data.ccdSweptSphereRadius);
	    }
	    _parseShape(shapesData) {
	        var shapeCount = shapesData.length;
	        if (shapeCount === 1) {
	            var shape = PhysicsComponent._creatShape(shapesData[0]);
	            this.colliderShape = shape;
	        }
	        else {
	            var compoundShape = new CompoundColliderShape();
	            for (var i = 0; i < shapeCount; i++) {
	                shape = PhysicsComponent._creatShape(shapesData[i]);
	                compoundShape.addChildShape(shape);
	            }
	            this.colliderShape = compoundShape;
	        }
	    }
	    _onScaleChange(scale) {
	        this._colliderShape._setScale(scale);
	    }
	    _setTransformFlag(type, value) {
	        if (value)
	            this._transformFlag |= type;
	        else
	            this._transformFlag &= ~type;
	    }
	    _getTransformFlag(type) {
	        return (this._transformFlag & type) != 0;
	    }
	    _addToSimulation() {
	    }
	    _removeFromSimulation() {
	    }
	    _derivePhysicsTransformation(force) {
	        this._innerDerivePhysicsTransformation(this._nativeColliderObject.getWorldTransform(), force);
	    }
	    _innerDerivePhysicsTransformation(physicTransformOut, force) {
	        var transform = this.owner._transform;
	        var rotation = transform.rotation;
	        if (force || this._getTransformFlag(Transform3D.TRANSFORM_WORLDPOSITION)) {
	            var shapeOffset = this._colliderShape.localOffset;
	            var position = transform.position;
	            var nativePosition = PhysicsComponent._nativeVector30;
	            if (shapeOffset.x !== 0 || shapeOffset.y !== 0 || shapeOffset.z !== 0) {
	                var physicPosition = PhysicsComponent._tempVector30;
	                PhysicsComponent.physicVector3TransformQuat(shapeOffset, rotation.x, rotation.y, rotation.z, rotation.w, physicPosition);
	                Vector3.add(position, physicPosition, physicPosition);
	                nativePosition.setValue(-physicPosition.x, physicPosition.y, physicPosition.z);
	            }
	            else {
	                nativePosition.setValue(-position.x, position.y, position.z);
	            }
	            physicTransformOut.setOrigin(nativePosition);
	            this._setTransformFlag(Transform3D.TRANSFORM_WORLDPOSITION, false);
	        }
	        if (force || this._getTransformFlag(Transform3D.TRANSFORM_WORLDQUATERNION)) {
	            var shapeRotation = this._colliderShape.localRotation;
	            var nativeRotation = PhysicsComponent._nativeQuaternion0;
	            if (shapeRotation.x !== 0 || shapeRotation.y !== 0 || shapeRotation.z !== 0 || shapeRotation.w !== 1) {
	                var physicRotation = PhysicsComponent._tempQuaternion0;
	                PhysicsComponent.physicQuaternionMultiply(rotation.x, rotation.y, rotation.z, rotation.w, shapeRotation, physicRotation);
	                nativeRotation.setValue(-physicRotation.x, physicRotation.y, physicRotation.z, -physicRotation.w);
	            }
	            else {
	                nativeRotation.setValue(-rotation.x, rotation.y, rotation.z, -rotation.w);
	            }
	            physicTransformOut.setRotation(nativeRotation);
	            this._setTransformFlag(Transform3D.TRANSFORM_WORLDQUATERNION, false);
	        }
	        if (force || this._getTransformFlag(Transform3D.TRANSFORM_WORLDSCALE)) {
	            this._onScaleChange(transform.getWorldLossyScale());
	            this._setTransformFlag(Transform3D.TRANSFORM_WORLDSCALE, false);
	        }
	    }
	    _updateTransformComponent(physicsTransform) {
	        var localOffset = this._colliderShape.localOffset;
	        var localRotation = this._colliderShape.localRotation;
	        var transform = this.owner._transform;
	        var position = transform.position;
	        var rotation = transform.rotation;
	        var nativePosition = physicsTransform.getOrigin();
	        var nativeRotation = physicsTransform.getRotation();
	        var nativeRotX = -nativeRotation.x();
	        var nativeRotY = nativeRotation.y();
	        var nativeRotZ = nativeRotation.z();
	        var nativeRotW = -nativeRotation.w();
	        if (localOffset.x !== 0 || localOffset.y !== 0 || localOffset.z !== 0) {
	            var rotShapePosition = PhysicsComponent._tempVector30;
	            PhysicsComponent.physicVector3TransformQuat(localOffset, nativeRotX, nativeRotY, nativeRotZ, nativeRotW, rotShapePosition);
	            position.x = -nativePosition.x() - rotShapePosition.x;
	            position.y = nativePosition.y() - rotShapePosition.y;
	            position.z = nativePosition.z() - rotShapePosition.z;
	        }
	        else {
	            position.x = -nativePosition.x();
	            position.y = nativePosition.y();
	            position.z = nativePosition.z();
	        }
	        transform.position = position;
	        if (localRotation.x !== 0 || localRotation.y !== 0 || localRotation.z !== 0 || localRotation.w !== 1) {
	            var invertShapeRotaion = PhysicsComponent._tempQuaternion0;
	            localRotation.invert(invertShapeRotaion);
	            PhysicsComponent.physicQuaternionMultiply(nativeRotX, nativeRotY, nativeRotZ, nativeRotW, invertShapeRotaion, rotation);
	        }
	        else {
	            rotation.x = nativeRotX;
	            rotation.y = nativeRotY;
	            rotation.z = nativeRotZ;
	            rotation.w = nativeRotW;
	        }
	        transform.rotation = rotation;
	    }
	    _onEnable() {
	        this._simulation = this.owner._scene.physicsSimulation;
	        this._nativeColliderObject.setContactProcessingThreshold(1e30);
	        if (this._colliderShape && this._enabled) {
	            this._derivePhysicsTransformation(true);
	            this._addToSimulation();
	        }
	    }
	    _onDisable() {
	        if (this._colliderShape && this._enabled) {
	            this._removeFromSimulation();
	            (this._inPhysicUpdateListIndex !== -1) && (this._simulation._physicsUpdateList.remove(this));
	        }
	        this._simulation = null;
	    }
	    _onShapeChange(colShape) {
	        var btColObj = this._nativeColliderObject;
	        var flags = btColObj.getCollisionFlags();
	        if (colShape.needsCustomCollisionCallback) {
	            if ((flags & PhysicsComponent.COLLISIONFLAGS_CUSTOM_MATERIAL_CALLBACK) === 0)
	                btColObj.setCollisionFlags(flags | PhysicsComponent.COLLISIONFLAGS_CUSTOM_MATERIAL_CALLBACK);
	        }
	        else {
	            if ((flags & PhysicsComponent.COLLISIONFLAGS_CUSTOM_MATERIAL_CALLBACK) > 0)
	                btColObj.setCollisionFlags(flags ^ PhysicsComponent.COLLISIONFLAGS_CUSTOM_MATERIAL_CALLBACK);
	        }
	    }
	    _onAdded() {
	        this.enabled = this._enabled;
	        this.restitution = this._restitution;
	        this.friction = this._friction;
	        this.rollingFriction = this._rollingFriction;
	        this.ccdMotionThreshold = this._ccdMotionThreshold;
	        this.ccdSweptSphereRadius = this._ccdSweptSphereRadius;
	        this.owner.transform.on(Laya.Event.TRANSFORM_CHANGED, this, this._onTransformChanged);
	    }
	    _onDestroy() {
	        var physics3D = Physics3D._physics3D;
	        delete PhysicsComponent._physicObjectsMap[this.id];
	        physics3D.destroy(this._nativeColliderObject);
	        this._colliderShape.destroy();
	        super._onDestroy();
	        this._nativeColliderObject = null;
	        this._colliderShape = null;
	        this._simulation = null;
	        this.owner.transform.off(Laya.Event.TRANSFORM_CHANGED, this, this._onTransformChanged);
	    }
	    _onTransformChanged(flag) {
	        if (PhysicsComponent._addUpdateList) {
	            flag &= Transform3D.TRANSFORM_WORLDPOSITION | Transform3D.TRANSFORM_WORLDQUATERNION | Transform3D.TRANSFORM_WORLDSCALE;
	            if (flag) {
	                this._transformFlag |= flag;
	                if (this._isValid() && this._inPhysicUpdateListIndex === -1)
	                    this._simulation._physicsUpdateList.add(this);
	            }
	        }
	    }
	    _cloneTo(dest) {
	        var destPhysicsComponent = dest;
	        destPhysicsComponent.restitution = this._restitution;
	        destPhysicsComponent.friction = this._friction;
	        destPhysicsComponent.rollingFriction = this._rollingFriction;
	        destPhysicsComponent.ccdMotionThreshold = this._ccdMotionThreshold;
	        destPhysicsComponent.ccdSweptSphereRadius = this._ccdSweptSphereRadius;
	        destPhysicsComponent.collisionGroup = this._collisionGroup;
	        destPhysicsComponent.canCollideWith = this._canCollideWith;
	        destPhysicsComponent.canScaleShape = this.canScaleShape;
	        (this._colliderShape) && (destPhysicsComponent.colliderShape = this._colliderShape.clone());
	    }
	}
	PhysicsComponent.ACTIVATIONSTATE_ACTIVE_TAG = 1;
	PhysicsComponent.ACTIVATIONSTATE_ISLAND_SLEEPING = 2;
	PhysicsComponent.ACTIVATIONSTATE_WANTS_DEACTIVATION = 3;
	PhysicsComponent.ACTIVATIONSTATE_DISABLE_DEACTIVATION = 4;
	PhysicsComponent.ACTIVATIONSTATE_DISABLE_SIMULATION = 5;
	PhysicsComponent.COLLISIONFLAGS_STATIC_OBJECT = 1;
	PhysicsComponent.COLLISIONFLAGS_KINEMATIC_OBJECT = 2;
	PhysicsComponent.COLLISIONFLAGS_NO_CONTACT_RESPONSE = 4;
	PhysicsComponent.COLLISIONFLAGS_CUSTOM_MATERIAL_CALLBACK = 8;
	PhysicsComponent.COLLISIONFLAGS_CHARACTER_OBJECT = 16;
	PhysicsComponent.COLLISIONFLAGS_DISABLE_VISUALIZE_OBJECT = 32;
	PhysicsComponent.COLLISIONFLAGS_DISABLE_SPU_COLLISION_PROCESSING = 64;
	PhysicsComponent._tempVector30 = new Vector3();
	PhysicsComponent._tempQuaternion0 = new Quaternion();
	PhysicsComponent._tempQuaternion1 = new Quaternion();
	PhysicsComponent._tempMatrix4x40 = new Matrix4x4();
	PhysicsComponent._physicObjectsMap = {};
	PhysicsComponent._addUpdateList = true;

	class PhysicsSimulation {
	    constructor(configuration, flags = 0) {
	        this._gravity = new Vector3(0, -10, 0);
	        this._nativeVector3Zero = new Physics3D._physics3D.btVector3(0, 0, 0);
	        this._nativeDefaultQuaternion = new Physics3D._physics3D.btQuaternion(0, 0, 0, -1);
	        this._collisionsUtils = new CollisionTool();
	        this._previousFrameCollisions = [];
	        this._currentFrameCollisions = [];
	        this._physicsUpdateList = new PhysicsUpdateList();
	        this._characters = [];
	        this._updatedRigidbodies = 0;
	        this.maxSubSteps = 1;
	        this.fixedTimeStep = 1.0 / 60.0;
	        this.maxSubSteps = configuration.maxSubSteps;
	        this.fixedTimeStep = configuration.fixedTimeStep;
	        var physics3D = Physics3D._physics3D;
	        this._nativeCollisionConfiguration = new physics3D.btDefaultCollisionConfiguration();
	        this._nativeDispatcher = new physics3D.btCollisionDispatcher(this._nativeCollisionConfiguration);
	        this._nativeBroadphase = new physics3D.btDbvtBroadphase();
	        this._nativeBroadphase.getOverlappingPairCache().setInternalGhostPairCallback(new physics3D.btGhostPairCallback());
	        var conFlags = configuration.flags;
	        if (conFlags & PhysicsSimulation.PHYSICSENGINEFLAGS_COLLISIONSONLY) {
	            this._nativeCollisionWorld = new physics3D.btCollisionWorld(this._nativeDispatcher, this._nativeBroadphase, this._nativeCollisionConfiguration);
	        }
	        else if (conFlags & PhysicsSimulation.PHYSICSENGINEFLAGS_SOFTBODYSUPPORT) {
	            throw "PhysicsSimulation:SoftBody processing is not yet available";
	        }
	        else {
	            var solver = new physics3D.btSequentialImpulseConstraintSolver();
	            this._nativeDiscreteDynamicsWorld = new physics3D.btDiscreteDynamicsWorld(this._nativeDispatcher, this._nativeBroadphase, solver, this._nativeCollisionConfiguration);
	            this._nativeCollisionWorld = this._nativeDiscreteDynamicsWorld;
	        }
	        if (this._nativeDiscreteDynamicsWorld) {
	            this._nativeSolverInfo = this._nativeDiscreteDynamicsWorld.getSolverInfo();
	            this._nativeDispatchInfo = this._nativeDiscreteDynamicsWorld.getDispatchInfo();
	        }
	        this._nativeClosestRayResultCallback = new physics3D.ClosestRayResultCallback(this._nativeVector3Zero, this._nativeVector3Zero);
	        this._nativeAllHitsRayResultCallback = new physics3D.AllHitsRayResultCallback(this._nativeVector3Zero, this._nativeVector3Zero);
	        this._nativeClosestConvexResultCallback = new physics3D.ClosestConvexResultCallback(this._nativeVector3Zero, this._nativeVector3Zero);
	        this._nativeAllConvexResultCallback = new physics3D.AllConvexResultCallback(this._nativeVector3Zero, this._nativeVector3Zero);
	        physics3D._btGImpactCollisionAlgorithm_RegisterAlgorithm(this._nativeDispatcher.a);
	    }
	    static __init__() {
	        PhysicsSimulation._nativeTempVector30 = new Physics3D._physics3D.btVector3(0, 0, 0);
	        PhysicsSimulation._nativeTempVector31 = new Physics3D._physics3D.btVector3(0, 0, 0);
	        PhysicsSimulation._nativeTempQuaternion0 = new Physics3D._physics3D.btQuaternion(0, 0, 0, 1);
	        PhysicsSimulation._nativeTempQuaternion1 = new Physics3D._physics3D.btQuaternion(0, 0, 0, 1);
	        PhysicsSimulation._nativeTempTransform0 = new Physics3D._physics3D.btTransform();
	        PhysicsSimulation._nativeTempTransform1 = new Physics3D._physics3D.btTransform();
	    }
	    static createConstraint() {
	    }
	    get continuousCollisionDetection() {
	        return this._nativeDispatchInfo.get_m_useContinuous();
	    }
	    set continuousCollisionDetection(value) {
	        this._nativeDispatchInfo.set_m_useContinuous(value);
	    }
	    get gravity() {
	        if (!this._nativeDiscreteDynamicsWorld)
	            throw "Simulation:Cannot perform this action when the physics engine is set to CollisionsOnly";
	        return this._gravity;
	    }
	    set gravity(value) {
	        if (!this._nativeDiscreteDynamicsWorld)
	            throw "Simulation:Cannot perform this action when the physics engine is set to CollisionsOnly";
	        this._gravity = value;
	        var nativeGravity = PhysicsSimulation._nativeTempVector30;
	        nativeGravity.setValue(-value.x, value.y, value.z);
	        this._nativeDiscreteDynamicsWorld.setGravity(nativeGravity);
	    }
	    get speculativeContactRestitution() {
	        if (!this._nativeDiscreteDynamicsWorld)
	            throw "Simulation:Cannot Cannot perform this action when the physics engine is set to CollisionsOnly";
	        return this._nativeDiscreteDynamicsWorld.getApplySpeculativeContactRestitution();
	    }
	    set speculativeContactRestitution(value) {
	        if (!this._nativeDiscreteDynamicsWorld)
	            throw "Simulation:Cannot Cannot perform this action when the physics engine is set to CollisionsOnly";
	        this._nativeDiscreteDynamicsWorld.setApplySpeculativeContactRestitution(value);
	    }
	    _simulate(deltaTime) {
	        this._updatedRigidbodies = 0;
	        if (this._nativeDiscreteDynamicsWorld)
	            this._nativeDiscreteDynamicsWorld.stepSimulation(deltaTime, this.maxSubSteps, this.fixedTimeStep);
	        else
	            this._nativeCollisionWorld.PerformDiscreteCollisionDetection();
	    }
	    _destroy() {
	        var physics3D = Physics3D._physics3D;
	        if (this._nativeDiscreteDynamicsWorld) {
	            physics3D.destroy(this._nativeDiscreteDynamicsWorld);
	            this._nativeDiscreteDynamicsWorld = null;
	        }
	        else {
	            physics3D.destroy(this._nativeCollisionWorld);
	            this._nativeCollisionWorld = null;
	        }
	        physics3D.destroy(this._nativeBroadphase);
	        this._nativeBroadphase = null;
	        physics3D.destroy(this._nativeDispatcher);
	        this._nativeDispatcher = null;
	        physics3D.destroy(this._nativeCollisionConfiguration);
	        this._nativeCollisionConfiguration = null;
	    }
	    _addPhysicsCollider(component, group, mask) {
	        this._nativeCollisionWorld.addCollisionObject(component._nativeColliderObject, group, mask);
	    }
	    _removePhysicsCollider(component) {
	        this._nativeCollisionWorld.removeCollisionObject(component._nativeColliderObject);
	    }
	    _addRigidBody(rigidBody, group, mask) {
	        if (!this._nativeDiscreteDynamicsWorld)
	            throw "Simulation:Cannot perform this action when the physics engine is set to CollisionsOnly";
	        this._nativeCollisionWorld.addRigidBody(rigidBody._nativeColliderObject, group, mask);
	    }
	    _removeRigidBody(rigidBody) {
	        if (!this._nativeDiscreteDynamicsWorld)
	            throw "Simulation:Cannot perform this action when the physics engine is set to CollisionsOnly";
	        this._nativeCollisionWorld.removeRigidBody(rigidBody._nativeColliderObject);
	    }
	    _addCharacter(character, group, mask) {
	        if (!this._nativeDiscreteDynamicsWorld)
	            throw "Simulation:Cannot perform this action when the physics engine is set to CollisionsOnly";
	        this._nativeCollisionWorld.addCollisionObject(character._nativeColliderObject, group, mask);
	        this._nativeCollisionWorld.addAction(character._nativeKinematicCharacter);
	    }
	    _removeCharacter(character) {
	        if (!this._nativeDiscreteDynamicsWorld)
	            throw "Simulation:Cannot perform this action when the physics engine is set to CollisionsOnly";
	        this._nativeCollisionWorld.removeCollisionObject(character._nativeColliderObject);
	        this._nativeCollisionWorld.removeAction(character._nativeKinematicCharacter);
	    }
	    raycastFromTo(from, to, out = null, collisonGroup = Physics3DUtils.COLLISIONFILTERGROUP_ALLFILTER, collisionMask = Physics3DUtils.COLLISIONFILTERGROUP_ALLFILTER) {
	        var rayResultCall = this._nativeClosestRayResultCallback;
	        var rayFrom = PhysicsSimulation._nativeTempVector30;
	        var rayTo = PhysicsSimulation._nativeTempVector31;
	        rayFrom.setValue(-from.x, from.y, from.z);
	        rayTo.setValue(-to.x, to.y, to.z);
	        rayResultCall.set_m_rayFromWorld(rayFrom);
	        rayResultCall.set_m_rayToWorld(rayTo);
	        rayResultCall.set_m_collisionFilterGroup(collisonGroup);
	        rayResultCall.set_m_collisionFilterMask(collisionMask);
	        rayResultCall.set_m_collisionObject(null);
	        rayResultCall.set_m_closestHitFraction(1);
	        this._nativeCollisionWorld.rayTest(rayFrom, rayTo, rayResultCall);
	        if (rayResultCall.hasHit()) {
	            if (out) {
	                out.succeeded = true;
	                out.collider = PhysicsComponent._physicObjectsMap[rayResultCall.get_m_collisionObject().getUserIndex()];
	                out.hitFraction = rayResultCall.get_m_closestHitFraction();
	                var nativePoint = rayResultCall.get_m_hitPointWorld();
	                var point = out.point;
	                point.x = -nativePoint.x();
	                point.y = nativePoint.y();
	                point.z = nativePoint.z();
	                var nativeNormal = rayResultCall.get_m_hitNormalWorld();
	                var normal = out.normal;
	                normal.x = -nativeNormal.x();
	                normal.y = nativeNormal.y();
	                normal.z = nativeNormal.z();
	            }
	            return true;
	        }
	        else {
	            if (out)
	                out.succeeded = false;
	            return false;
	        }
	    }
	    raycastAllFromTo(from, to, out, collisonGroup = Physics3DUtils.COLLISIONFILTERGROUP_ALLFILTER, collisionMask = Physics3DUtils.COLLISIONFILTERGROUP_ALLFILTER) {
	        var rayResultCall = this._nativeAllHitsRayResultCallback;
	        var rayFrom = PhysicsSimulation._nativeTempVector30;
	        var rayTo = PhysicsSimulation._nativeTempVector31;
	        out.length = 0;
	        rayFrom.setValue(-from.x, from.y, from.z);
	        rayTo.setValue(-to.x, to.y, to.z);
	        rayResultCall.set_m_rayFromWorld(rayFrom);
	        rayResultCall.set_m_rayToWorld(rayTo);
	        rayResultCall.set_m_collisionFilterGroup(collisonGroup);
	        rayResultCall.set_m_collisionFilterMask(collisionMask);
	        var collisionObjects = rayResultCall.get_m_collisionObjects();
	        var nativePoints = rayResultCall.get_m_hitPointWorld();
	        var nativeNormals = rayResultCall.get_m_hitNormalWorld();
	        var nativeFractions = rayResultCall.get_m_hitFractions();
	        collisionObjects.clear();
	        nativePoints.clear();
	        nativeNormals.clear();
	        nativeFractions.clear();
	        this._nativeCollisionWorld.rayTest(rayFrom, rayTo, rayResultCall);
	        var count = collisionObjects.size();
	        if (count > 0) {
	            this._collisionsUtils.recoverAllHitResultsPool();
	            for (var i = 0; i < count; i++) {
	                var hitResult = this._collisionsUtils.getHitResult();
	                out.push(hitResult);
	                hitResult.succeeded = true;
	                hitResult.collider = PhysicsComponent._physicObjectsMap[collisionObjects.at(i).getUserIndex()];
	                hitResult.hitFraction = nativeFractions.at(i);
	                var nativePoint = nativePoints.at(i);
	                var pointE = hitResult.point;
	                pointE.x = -nativePoint.x();
	                pointE.y = nativePoint.y();
	                pointE.z = nativePoint.z();
	                var nativeNormal = nativeNormals.at(i);
	                var normalE = hitResult.normal;
	                normalE.x = -nativeNormal.x();
	                normalE.y = nativeNormal.y();
	                normalE.z = nativeNormal.z();
	            }
	            return true;
	        }
	        else {
	            return false;
	        }
	    }
	    rayCast(ray, outHitResult = null, distance = 2147483647, collisonGroup = Physics3DUtils.COLLISIONFILTERGROUP_ALLFILTER, collisionMask = Physics3DUtils.COLLISIONFILTERGROUP_ALLFILTER) {
	        var from = ray.origin;
	        var to = PhysicsSimulation._tempVector30;
	        Vector3.normalize(ray.direction, to);
	        Vector3.scale(to, distance, to);
	        Vector3.add(from, to, to);
	        return this.raycastFromTo(from, to, outHitResult, collisonGroup, collisionMask);
	    }
	    rayCastAll(ray, out, distance = 2147483647, collisonGroup = Physics3DUtils.COLLISIONFILTERGROUP_ALLFILTER, collisionMask = Physics3DUtils.COLLISIONFILTERGROUP_ALLFILTER) {
	        var from = ray.origin;
	        var to = PhysicsSimulation._tempVector30;
	        Vector3.normalize(ray.direction, to);
	        Vector3.scale(to, distance, to);
	        Vector3.add(from, to, to);
	        return this.raycastAllFromTo(from, to, out, collisonGroup, collisionMask);
	    }
	    shapeCast(shape, fromPosition, toPosition, out = null, fromRotation = null, toRotation = null, collisonGroup = Physics3DUtils.COLLISIONFILTERGROUP_ALLFILTER, collisionMask = Physics3DUtils.COLLISIONFILTERGROUP_ALLFILTER, allowedCcdPenetration = 0.0) {
	        var convexResultCall = this._nativeClosestConvexResultCallback;
	        var convexPosFrom = PhysicsSimulation._nativeTempVector30;
	        var convexPosTo = PhysicsSimulation._nativeTempVector31;
	        var convexRotFrom = PhysicsSimulation._nativeTempQuaternion0;
	        var convexRotTo = PhysicsSimulation._nativeTempQuaternion1;
	        var convexTransform = PhysicsSimulation._nativeTempTransform0;
	        var convexTransTo = PhysicsSimulation._nativeTempTransform1;
	        var sweepShape = shape._nativeShape;
	        convexPosFrom.setValue(-fromPosition.x, fromPosition.y, fromPosition.z);
	        convexPosTo.setValue(-toPosition.x, toPosition.y, toPosition.z);
	        convexResultCall.set_m_collisionFilterGroup(collisonGroup);
	        convexResultCall.set_m_collisionFilterMask(collisionMask);
	        convexTransform.setOrigin(convexPosFrom);
	        convexTransTo.setOrigin(convexPosTo);
	        if (fromRotation) {
	            convexRotFrom.setValue(-fromRotation.x, fromRotation.y, fromRotation.z, -fromRotation.w);
	            convexTransform.setRotation(convexRotFrom);
	        }
	        else {
	            convexTransform.setRotation(this._nativeDefaultQuaternion);
	        }
	        if (toRotation) {
	            convexRotTo.setValue(-toRotation.x, toRotation.y, toRotation.z, -toRotation.w);
	            convexTransTo.setRotation(convexRotTo);
	        }
	        else {
	            convexTransTo.setRotation(this._nativeDefaultQuaternion);
	        }
	        convexResultCall.set_m_hitCollisionObject(null);
	        convexResultCall.set_m_closestHitFraction(1);
	        this._nativeCollisionWorld.convexSweepTest(sweepShape, convexTransform, convexTransTo, convexResultCall, allowedCcdPenetration);
	        if (convexResultCall.hasHit()) {
	            if (out) {
	                out.succeeded = true;
	                out.collider = PhysicsComponent._physicObjectsMap[convexResultCall.get_m_hitCollisionObject().getUserIndex()];
	                out.hitFraction = convexResultCall.get_m_closestHitFraction();
	                var nativePoint = convexResultCall.get_m_hitPointWorld();
	                var nativeNormal = convexResultCall.get_m_hitNormalWorld();
	                var point = out.point;
	                var normal = out.normal;
	                point.x = -nativePoint.x();
	                point.y = nativePoint.y();
	                point.z = nativePoint.z();
	                normal.x = -nativeNormal.x();
	                normal.y = nativeNormal.y();
	                normal.z = nativeNormal.z();
	            }
	            return true;
	        }
	        else {
	            if (out)
	                out.succeeded = false;
	            return false;
	        }
	    }
	    shapeCastAll(shape, fromPosition, toPosition, out, fromRotation = null, toRotation = null, collisonGroup = Physics3DUtils.COLLISIONFILTERGROUP_ALLFILTER, collisionMask = Physics3DUtils.COLLISIONFILTERGROUP_ALLFILTER, allowedCcdPenetration = 0.0) {
	        var convexResultCall = this._nativeAllConvexResultCallback;
	        var convexPosFrom = PhysicsSimulation._nativeTempVector30;
	        var convexPosTo = PhysicsSimulation._nativeTempVector31;
	        var convexRotFrom = PhysicsSimulation._nativeTempQuaternion0;
	        var convexRotTo = PhysicsSimulation._nativeTempQuaternion1;
	        var convexTransform = PhysicsSimulation._nativeTempTransform0;
	        var convexTransTo = PhysicsSimulation._nativeTempTransform1;
	        var sweepShape = shape._nativeShape;
	        out.length = 0;
	        convexPosFrom.setValue(-fromPosition.x, fromPosition.y, fromPosition.z);
	        convexPosTo.setValue(-toPosition.x, toPosition.y, toPosition.z);
	        convexResultCall.set_m_collisionFilterGroup(collisonGroup);
	        convexResultCall.set_m_collisionFilterMask(collisionMask);
	        convexTransform.setOrigin(convexPosFrom);
	        convexTransTo.setOrigin(convexPosTo);
	        if (fromRotation) {
	            convexRotFrom.setValue(-fromRotation.x, fromRotation.y, fromRotation.z, -fromRotation.w);
	            convexTransform.setRotation(convexRotFrom);
	        }
	        else {
	            convexTransform.setRotation(this._nativeDefaultQuaternion);
	        }
	        if (toRotation) {
	            convexRotTo.setValue(-toRotation.x, toRotation.y, toRotation.z, -toRotation.w);
	            convexTransTo.setRotation(convexRotTo);
	        }
	        else {
	            convexTransTo.setRotation(this._nativeDefaultQuaternion);
	        }
	        var collisionObjects = convexResultCall.get_m_collisionObjects();
	        collisionObjects.clear();
	        this._nativeCollisionWorld.convexSweepTest(sweepShape, convexTransform, convexTransTo, convexResultCall, allowedCcdPenetration);
	        var count = collisionObjects.size();
	        if (count > 0) {
	            var nativePoints = convexResultCall.get_m_hitPointWorld();
	            var nativeNormals = convexResultCall.get_m_hitNormalWorld();
	            var nativeFractions = convexResultCall.get_m_hitFractions();
	            for (var i = 0; i < count; i++) {
	                var hitResult = this._collisionsUtils.getHitResult();
	                out.push(hitResult);
	                hitResult.succeeded = true;
	                hitResult.collider = PhysicsComponent._physicObjectsMap[collisionObjects.at(i).getUserIndex()];
	                hitResult.hitFraction = nativeFractions.at(i);
	                var nativePoint = nativePoints.at(i);
	                var point = hitResult.point;
	                point.x = -nativePoint.x();
	                point.y = nativePoint.y();
	                point.z = nativePoint.z();
	                var nativeNormal = nativeNormals.at(i);
	                var normal = hitResult.normal;
	                normal.x = -nativeNormal.x();
	                normal.y = nativeNormal.y();
	                normal.z = nativeNormal.z();
	            }
	            return true;
	        }
	        else {
	            return false;
	        }
	    }
	    addConstraint(constraint, disableCollisionsBetweenLinkedBodies = false) {
	        if (!this._nativeDiscreteDynamicsWorld)
	            throw "Cannot perform this action when the physics engine is set to CollisionsOnly";
	        this._nativeDiscreteDynamicsWorld.addConstraint(constraint._nativeConstraint, disableCollisionsBetweenLinkedBodies);
	        constraint._simulation = this;
	    }
	    removeConstraint(constraint) {
	        if (!this._nativeDiscreteDynamicsWorld)
	            throw "Cannot perform this action when the physics engine is set to CollisionsOnly";
	        this._nativeDiscreteDynamicsWorld.removeConstraint(constraint._nativeConstraint);
	    }
	    _updatePhysicsTransformFromRender() {
	        var elements = this._physicsUpdateList.elements;
	        for (var i = 0, n = this._physicsUpdateList.length; i < n; i++) {
	            var physicCollider = elements[i];
	            physicCollider._derivePhysicsTransformation(false);
	            physicCollider._inPhysicUpdateListIndex = -1;
	        }
	        this._physicsUpdateList.length = 0;
	    }
	    _updateCharacters() {
	        for (var i = 0, n = this._characters.length; i < n; i++) {
	            var character = this._characters[i];
	            character._updateTransformComponent(character._nativeColliderObject.getWorldTransform());
	        }
	    }
	    _updateCollisions() {
	        this._collisionsUtils.recoverAllContactPointsPool();
	        var previous = this._currentFrameCollisions;
	        this._currentFrameCollisions = this._previousFrameCollisions;
	        this._currentFrameCollisions.length = 0;
	        this._previousFrameCollisions = previous;
	        var loopCount = Laya.Stat.loopCount;
	        var numManifolds = this._nativeDispatcher.getNumManifolds();
	        for (var i = 0; i < numManifolds; i++) {
	            var contactManifold = this._nativeDispatcher.getManifoldByIndexInternal(i);
	            var componentA = PhysicsComponent._physicObjectsMap[contactManifold.getBody0().getUserIndex()];
	            var componentB = PhysicsComponent._physicObjectsMap[contactManifold.getBody1().getUserIndex()];
	            var collision = null;
	            var isFirstCollision;
	            var contacts = null;
	            var isTrigger = componentA.isTrigger || componentB.isTrigger;
	            if (isTrigger && (componentA.owner._needProcessTriggers || componentB.owner._needProcessTriggers)) {
	                var numContacts = contactManifold.getNumContacts();
	                for (var j = 0; j < numContacts; j++) {
	                    var pt = contactManifold.getContactPoint(j);
	                    var distance = pt.getDistance();
	                    if (distance <= 0) {
	                        collision = this._collisionsUtils.getCollision(componentA, componentB);
	                        contacts = collision.contacts;
	                        isFirstCollision = collision._updateFrame !== loopCount;
	                        if (isFirstCollision) {
	                            collision._isTrigger = true;
	                            contacts.length = 0;
	                        }
	                        break;
	                    }
	                }
	            }
	            else if (componentA.owner._needProcessCollisions || componentB.owner._needProcessCollisions) {
	                if (componentA._enableProcessCollisions || componentB._enableProcessCollisions) {
	                    numContacts = contactManifold.getNumContacts();
	                    for (j = 0; j < numContacts; j++) {
	                        pt = contactManifold.getContactPoint(j);
	                        distance = pt.getDistance();
	                        if (distance <= 0) {
	                            var contactPoint = this._collisionsUtils.getContactPoints();
	                            contactPoint.colliderA = componentA;
	                            contactPoint.colliderB = componentB;
	                            contactPoint.distance = distance;
	                            var nativeNormal = pt.get_m_normalWorldOnB();
	                            var normal = contactPoint.normal;
	                            normal.x = -nativeNormal.x();
	                            normal.y = nativeNormal.y();
	                            normal.z = nativeNormal.z();
	                            var nativePostionA = pt.get_m_positionWorldOnA();
	                            var positionOnA = contactPoint.positionOnA;
	                            positionOnA.x = -nativePostionA.x();
	                            positionOnA.y = nativePostionA.y();
	                            positionOnA.z = nativePostionA.z();
	                            var nativePostionB = pt.get_m_positionWorldOnB();
	                            var positionOnB = contactPoint.positionOnB;
	                            positionOnB.x = -nativePostionB.x();
	                            positionOnB.y = nativePostionB.y();
	                            positionOnB.z = nativePostionB.z();
	                            if (!collision) {
	                                collision = this._collisionsUtils.getCollision(componentA, componentB);
	                                contacts = collision.contacts;
	                                isFirstCollision = collision._updateFrame !== loopCount;
	                                if (isFirstCollision) {
	                                    collision._isTrigger = false;
	                                    contacts.length = 0;
	                                }
	                            }
	                            contacts.push(contactPoint);
	                        }
	                    }
	                }
	            }
	            if (collision && isFirstCollision) {
	                this._currentFrameCollisions.push(collision);
	                collision._setUpdateFrame(loopCount);
	            }
	        }
	    }
	    _eventScripts() {
	        var loopCount = Laya.Stat.loopCount;
	        for (var i = 0, n = this._currentFrameCollisions.length; i < n; i++) {
	            var curFrameCol = this._currentFrameCollisions[i];
	            var colliderA = curFrameCol._colliderA;
	            var colliderB = curFrameCol._colliderB;
	            if (colliderA.destroyed || colliderB.destroyed)
	                continue;
	            if (loopCount - curFrameCol._lastUpdateFrame === 1) {
	                var ownerA = colliderA.owner;
	                var scriptsA = ownerA._scripts;
	                if (scriptsA) {
	                    if (curFrameCol._isTrigger) {
	                        if (ownerA._needProcessTriggers) {
	                            for (var j = 0, m = scriptsA.length; j < m; j++)
	                                scriptsA[j].onTriggerStay(colliderB);
	                        }
	                    }
	                    else {
	                        if (ownerA._needProcessCollisions) {
	                            for (j = 0, m = scriptsA.length; j < m; j++) {
	                                curFrameCol.other = colliderB;
	                                scriptsA[j].onCollisionStay(curFrameCol);
	                            }
	                        }
	                    }
	                }
	                var ownerB = colliderB.owner;
	                var scriptsB = ownerB._scripts;
	                if (scriptsB) {
	                    if (curFrameCol._isTrigger) {
	                        if (ownerB._needProcessTriggers) {
	                            for (j = 0, m = scriptsB.length; j < m; j++)
	                                scriptsB[j].onTriggerStay(colliderA);
	                        }
	                    }
	                    else {
	                        if (ownerB._needProcessCollisions) {
	                            for (j = 0, m = scriptsB.length; j < m; j++) {
	                                curFrameCol.other = colliderA;
	                                scriptsB[j].onCollisionStay(curFrameCol);
	                            }
	                        }
	                    }
	                }
	            }
	            else {
	                ownerA = colliderA.owner;
	                scriptsA = ownerA._scripts;
	                if (scriptsA) {
	                    if (curFrameCol._isTrigger) {
	                        if (ownerA._needProcessTriggers) {
	                            for (j = 0, m = scriptsA.length; j < m; j++)
	                                scriptsA[j].onTriggerEnter(colliderB);
	                        }
	                    }
	                    else {
	                        if (ownerA._needProcessCollisions) {
	                            for (j = 0, m = scriptsA.length; j < m; j++) {
	                                curFrameCol.other = colliderB;
	                                scriptsA[j].onCollisionEnter(curFrameCol);
	                            }
	                        }
	                    }
	                }
	                ownerB = colliderB.owner;
	                scriptsB = ownerB._scripts;
	                if (scriptsB) {
	                    if (curFrameCol._isTrigger) {
	                        if (ownerB._needProcessTriggers) {
	                            for (j = 0, m = scriptsB.length; j < m; j++)
	                                scriptsB[j].onTriggerEnter(colliderA);
	                        }
	                    }
	                    else {
	                        if (ownerB._needProcessCollisions) {
	                            for (j = 0, m = scriptsB.length; j < m; j++) {
	                                curFrameCol.other = colliderA;
	                                scriptsB[j].onCollisionEnter(curFrameCol);
	                            }
	                        }
	                    }
	                }
	            }
	        }
	        for (i = 0, n = this._previousFrameCollisions.length; i < n; i++) {
	            var preFrameCol = this._previousFrameCollisions[i];
	            var preColliderA = preFrameCol._colliderA;
	            var preColliderB = preFrameCol._colliderB;
	            if (preColliderA.destroyed || preColliderB.destroyed)
	                continue;
	            if (loopCount - preFrameCol._updateFrame === 1) {
	                this._collisionsUtils.recoverCollision(preFrameCol);
	                ownerA = preColliderA.owner;
	                scriptsA = ownerA._scripts;
	                if (scriptsA) {
	                    if (preFrameCol._isTrigger) {
	                        if (ownerA._needProcessTriggers) {
	                            for (j = 0, m = scriptsA.length; j < m; j++)
	                                scriptsA[j].onTriggerExit(preColliderB);
	                        }
	                    }
	                    else {
	                        if (ownerA._needProcessCollisions) {
	                            for (j = 0, m = scriptsA.length; j < m; j++) {
	                                preFrameCol.other = preColliderB;
	                                scriptsA[j].onCollisionExit(preFrameCol);
	                            }
	                        }
	                    }
	                }
	                ownerB = preColliderB.owner;
	                scriptsB = ownerB._scripts;
	                if (scriptsB) {
	                    if (preFrameCol._isTrigger) {
	                        if (ownerB._needProcessTriggers) {
	                            for (j = 0, m = scriptsB.length; j < m; j++)
	                                scriptsB[j].onTriggerExit(preColliderA);
	                        }
	                    }
	                    else {
	                        if (ownerB._needProcessCollisions) {
	                            for (j = 0, m = scriptsB.length; j < m; j++) {
	                                preFrameCol.other = preColliderA;
	                                scriptsB[j].onCollisionExit(preFrameCol);
	                            }
	                        }
	                    }
	                }
	            }
	        }
	    }
	    clearForces() {
	        if (!this._nativeDiscreteDynamicsWorld)
	            throw "Cannot perform this action when the physics engine is set to CollisionsOnly";
	        this._nativeDiscreteDynamicsWorld.clearForces();
	    }
	}
	PhysicsSimulation.PHYSICSENGINEFLAGS_NONE = 0x0;
	PhysicsSimulation.PHYSICSENGINEFLAGS_COLLISIONSONLY = 0x1;
	PhysicsSimulation.PHYSICSENGINEFLAGS_SOFTBODYSUPPORT = 0x2;
	PhysicsSimulation.PHYSICSENGINEFLAGS_MULTITHREADED = 0x4;
	PhysicsSimulation.PHYSICSENGINEFLAGS_USEHARDWAREWHENPOSSIBLE = 0x8;
	PhysicsSimulation.SOLVERMODE_RANDMIZE_ORDER = 1;
	PhysicsSimulation.SOLVERMODE_FRICTION_SEPARATE = 2;
	PhysicsSimulation.SOLVERMODE_USE_WARMSTARTING = 4;
	PhysicsSimulation.SOLVERMODE_USE_2_FRICTION_DIRECTIONS = 16;
	PhysicsSimulation.SOLVERMODE_ENABLE_FRICTION_DIRECTION_CACHING = 32;
	PhysicsSimulation.SOLVERMODE_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION = 64;
	PhysicsSimulation.SOLVERMODE_CACHE_FRIENDLY = 128;
	PhysicsSimulation.SOLVERMODE_SIMD = 256;
	PhysicsSimulation.SOLVERMODE_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS = 512;
	PhysicsSimulation.SOLVERMODE_ALLOW_ZERO_LENGTH_FRICTION_DIRECTIONS = 1024;
	PhysicsSimulation._tempVector30 = new Vector3();
	PhysicsSimulation.disableSimulation = false;

	class Input3D {
	    constructor() {
	        this._eventList = [];
	        this._mouseTouch = new MouseTouch();
	        this._touchPool = [];
	        this._touches = new SimpleSingletonList();
	        this._multiTouchEnabled = true;
	        this._pushEventList = ((e) => {
	            (e.cancelable) && (e.preventDefault());
	            this._eventList.push(e);
	        }).bind(this);
	    }
	    __init__(canvas, scene) {
	        this._scene = scene;
	        canvas.oncontextmenu = function (e) {
	            return false;
	        };
	    }
	    _onCanvasEvent(canvas) {
	        canvas.addEventListener('mousedown', this._pushEventList);
	        canvas.addEventListener('mouseup', this._pushEventList, true);
	        canvas.addEventListener('mousemove', this._pushEventList, true);
	        canvas.addEventListener("touchstart", this._pushEventList);
	        canvas.addEventListener("touchend", this._pushEventList, true);
	        canvas.addEventListener("touchmove", this._pushEventList, true);
	        canvas.addEventListener("touchcancel", this._pushEventList, true);
	    }
	    _offCanvasEvent(canvas) {
	        canvas.removeEventListener('mousedown', this._pushEventList);
	        canvas.removeEventListener('mouseup', this._pushEventList, true);
	        canvas.removeEventListener('mousemove', this._pushEventList, true);
	        canvas.removeEventListener("touchstart", this._pushEventList);
	        canvas.removeEventListener("touchend", this._pushEventList, true);
	        canvas.removeEventListener("touchmove", this._pushEventList, true);
	        canvas.removeEventListener("touchcancel", this._pushEventList, true);
	        this._eventList.length = 0;
	        this._touches.length = 0;
	    }
	    touchCount() {
	        return this._touches.length;
	    }
	    get multiTouchEnabled() {
	        return this._multiTouchEnabled;
	    }
	    set multiTouchEnabled(value) {
	        this._multiTouchEnabled = value;
	    }
	    _getTouch(touchID) {
	        var touch = this._touchPool[touchID];
	        if (!touch) {
	            touch = new Touch();
	            this._touchPool[touchID] = touch;
	            touch._identifier = touchID;
	        }
	        return touch;
	    }
	    _mouseTouchDown() {
	        var touch = this._mouseTouch;
	        var sprite = touch.sprite;
	        touch._pressedSprite = sprite;
	        touch._pressedLoopCount = Laya.Stat.loopCount;
	        if (sprite) {
	            var scripts = sprite._scripts;
	            if (scripts) {
	                for (var i = 0, n = scripts.length; i < n; i++)
	                    scripts[i].onMouseDown();
	            }
	        }
	    }
	    _mouseTouchUp() {
	        var i, n;
	        var touch = this._mouseTouch;
	        var lastPressedSprite = touch._pressedSprite;
	        touch._pressedSprite = null;
	        touch._pressedLoopCount = -1;
	        var sprite = touch.sprite;
	        if (sprite) {
	            if (sprite === lastPressedSprite) {
	                var scripts = sprite._scripts;
	                if (scripts) {
	                    for (i = 0, n = scripts.length; i < n; i++)
	                        scripts[i].onMouseClick();
	                }
	            }
	        }
	        if (lastPressedSprite) {
	            var lastScripts = lastPressedSprite._scripts;
	            if (lastScripts) {
	                for (i = 0, n = lastScripts.length; i < n; i++)
	                    lastScripts[i].onMouseUp();
	            }
	        }
	    }
	    _mouseTouchRayCast(cameras) {
	        var touchHitResult = Input3D._tempHitResult0;
	        var touchPos = Input3D._tempVector20;
	        var touchRay = Input3D._tempRay0;
	        touchHitResult.succeeded = false;
	        var x = this._mouseTouch.mousePositionX;
	        var y = this._mouseTouch.mousePositionY;
	        touchPos.x = x;
	        touchPos.y = y;
	        for (var i = cameras.length - 1; i >= 0; i--) {
	            var camera = cameras[i];
	            var viewport = camera.viewport;
	            if (touchPos.x >= viewport.x && touchPos.y >= viewport.y && touchPos.x <= viewport.width && touchPos.y <= viewport.height) {
	                camera.viewportPointToRay(touchPos, touchRay);
	                var sucess = this._scene._physicsSimulation.rayCast(touchRay, touchHitResult);
	                if (sucess || (camera.clearFlag === BaseCamera.CLEARFLAG_SOLIDCOLOR || camera.clearFlag === BaseCamera.CLEARFLAG_SKY))
	                    break;
	            }
	        }
	        var touch = this._mouseTouch;
	        var lastSprite = touch.sprite;
	        if (touchHitResult.succeeded) {
	            var touchSprite = touchHitResult.collider.owner;
	            touch.sprite = touchSprite;
	            var scripts = touchSprite._scripts;
	            if (lastSprite !== touchSprite) {
	                if (scripts) {
	                    for (var j = 0, m = scripts.length; j < m; j++)
	                        scripts[j].onMouseEnter();
	                }
	            }
	        }
	        else {
	            touch.sprite = null;
	        }
	        if (lastSprite && (lastSprite !== touchSprite)) {
	            var outScripts = lastSprite._scripts;
	            if (outScripts) {
	                for (j = 0, m = outScripts.length; j < m; j++)
	                    outScripts[j].onMouseOut();
	            }
	        }
	    }
	    _changeTouches(changedTouches, flag) {
	        var offsetX = 0, offsetY = 0;
	        var lastCount = this._touches.length;
	        for (var j = 0, m = changedTouches.length; j < m; j++) {
	            var nativeTouch = changedTouches[j];
	            var identifier = nativeTouch.identifier;
	            if (!this._multiTouchEnabled && identifier !== 0)
	                continue;
	            var touch = this._getTouch(identifier);
	            var pos = touch._position;
	            var mousePoint = Input3D._tempPoint;
	            mousePoint.setTo(nativeTouch.pageX, nativeTouch.pageY);
	            Laya.ILaya.stage._canvasTransform.invertTransformPoint(mousePoint);
	            var posX = mousePoint.x;
	            var posY = mousePoint.y;
	            switch (flag) {
	                case 0:
	                    this._touches.add(touch);
	                    offsetX += posX;
	                    offsetY += posY;
	                    break;
	                case 1:
	                    this._touches.remove(touch);
	                    offsetX -= posX;
	                    offsetY -= posY;
	                    break;
	                case 2:
	                    offsetX = posX - pos.x;
	                    offsetY = posY - pos.y;
	                    break;
	            }
	            pos.x = posX;
	            pos.y = posY;
	        }
	        var touchCount = this._touches.length;
	        if (touchCount === 0) {
	            this._mouseTouch.mousePositionX = 0;
	            this._mouseTouch.mousePositionY = 0;
	        }
	        else {
	            this._mouseTouch.mousePositionX = (this._mouseTouch.mousePositionX * lastCount + offsetX) / touchCount;
	            this._mouseTouch.mousePositionY = (this._mouseTouch.mousePositionY * lastCount + offsetY) / touchCount;
	        }
	    }
	    _update() {
	        var enablePhysics = Physics3D._enbalePhysics && !PhysicsSimulation.disableSimulation;
	        var i, n, j, m;
	        n = this._eventList.length;
	        var cameras = this._scene._cameraPool;
	        if (n > 0) {
	            var rayCast = false;
	            for (i = 0; i < n; i++) {
	                var e = this._eventList[i];
	                switch (e.type) {
	                    case "mousedown":
	                        (enablePhysics) && (this._mouseTouchDown());
	                        break;
	                    case "mouseup":
	                        (enablePhysics) && (this._mouseTouchUp());
	                        break;
	                    case "mousemove":
	                        var mousePoint = Input3D._tempPoint;
	                        mousePoint.setTo(e.pageX, e.pageY);
	                        Laya.ILaya.stage._canvasTransform.invertTransformPoint(mousePoint);
	                        this._mouseTouch.mousePositionX = mousePoint.x;
	                        this._mouseTouch.mousePositionY = mousePoint.y;
	                        (enablePhysics) && (rayCast = true);
	                        break;
	                    case "touchstart":
	                        var lastLength = this._touches.length;
	                        this._changeTouches(e.changedTouches, 0);
	                        if (enablePhysics) {
	                            rayCast = true;
	                            (lastLength === 0) && (this._mouseTouchDown());
	                        }
	                        break;
	                    case "touchend":
	                    case "touchcancel":
	                        this._changeTouches(e.changedTouches, 1);
	                        (enablePhysics && this._touches.length === 0) && (this._mouseTouchUp());
	                        break;
	                    case "touchmove":
	                        this._changeTouches(e.changedTouches, 2);
	                        (enablePhysics) && (rayCast = true);
	                        break;
	                    default:
	                        throw "Input3D:unkonwn event type.";
	                }
	            }
	            (rayCast) && (this._mouseTouchRayCast(cameras));
	            this._eventList.length = 0;
	        }
	        if (enablePhysics) {
	            var mouseTouch = this._mouseTouch;
	            var pressedSprite = mouseTouch._pressedSprite;
	            if (pressedSprite && (Laya.Stat.loopCount > mouseTouch._pressedLoopCount)) {
	                var pressedScripts = pressedSprite._scripts;
	                if (pressedScripts) {
	                    for (j = 0, m = pressedScripts.length; j < m; j++)
	                        pressedScripts[j].onMouseDrag();
	                }
	            }
	            var touchSprite = mouseTouch.sprite;
	            if (touchSprite) {
	                var scripts = touchSprite._scripts;
	                if (scripts) {
	                    for (j = 0, m = scripts.length; j < m; j++)
	                        scripts[j].onMouseOver();
	                }
	            }
	        }
	    }
	    getTouch(index) {
	        if (index < this._touches.length) {
	            return this._touches.elements[index];
	        }
	        else {
	            return null;
	        }
	    }
	}
	Input3D._tempPoint = new Laya.Point();
	Input3D._tempVector20 = new Vector2();
	Input3D._tempRay0 = new Ray(new Vector3(), new Vector3());
	Input3D._tempHitResult0 = new HitResult();

	class PhysicsSettings {
	    constructor() {
	        this.flags = 0;
	        this.maxSubSteps = 1;
	        this.fixedTimeStep = 1.0 / 60.0;
	    }
	}

	class VertexPositionTexture0 {
	    static get vertexDeclaration() {
	        return VertexPositionTexture0._vertexDeclaration;
	    }
	    static __init__() {
	        VertexPositionTexture0._vertexDeclaration = new VertexDeclaration(20, [new VertexElement(0, VertexElementFormat.Vector3, VertexMesh.MESH_POSITION0),
	            new VertexElement(12, VertexElementFormat.Vector2, VertexMesh.MESH_TEXTURECOORDINATE0)]);
	    }
	    get position() {
	        return this._position;
	    }
	    get textureCoordinate0() {
	        return this._textureCoordinate0;
	    }
	    get vertexDeclaration() {
	        return VertexPositionTexture0._vertexDeclaration;
	    }
	    constructor(position, textureCoordinate0) {
	        this._position = position;
	        this._textureCoordinate0 = textureCoordinate0;
	    }
	}

	class SkyDome extends SkyMesh {
	    constructor(stacks = 48, slices = 48) {
	        super();
	        var gl = Laya.LayaGL.instance;
	        this._stacks = stacks;
	        this._slices = slices;
	        var vertexDeclaration = VertexPositionTexture0.vertexDeclaration;
	        var vertexFloatCount = vertexDeclaration.vertexStride / 4;
	        var numberVertices = (this._stacks + 1) * (this._slices + 1);
	        var numberIndices = (3 * this._stacks * (this._slices + 1)) * 2;
	        var vertices = new Float32Array(numberVertices * vertexFloatCount);
	        var indices = new Uint16Array(numberIndices);
	        var stackAngle = Math.PI / this._stacks;
	        var sliceAngle = (Math.PI * 2.0) / this._slices;
	        var vertexIndex = 0;
	        var vertexCount = 0;
	        var indexCount = 0;
	        for (var stack = 0; stack < (this._stacks + 1); stack++) {
	            var r = Math.sin(stack * stackAngle);
	            var y = Math.cos(stack * stackAngle);
	            for (var slice = 0; slice < (this._slices + 1); slice++) {
	                var x = r * Math.sin(slice * sliceAngle);
	                var z = r * Math.cos(slice * sliceAngle);
	                vertices[vertexCount + 0] = x * SkyDome._radius;
	                vertices[vertexCount + 1] = y * SkyDome._radius;
	                vertices[vertexCount + 2] = z * SkyDome._radius;
	                vertices[vertexCount + 3] = -(slice / this._slices) + 0.75;
	                vertices[vertexCount + 4] = stack / this._stacks;
	                vertexCount += vertexFloatCount;
	                if (stack != (this._stacks - 1)) {
	                    indices[indexCount++] = vertexIndex + 1;
	                    indices[indexCount++] = vertexIndex;
	                    indices[indexCount++] = vertexIndex + (this._slices + 1);
	                    indices[indexCount++] = vertexIndex + (this._slices + 1);
	                    indices[indexCount++] = vertexIndex;
	                    indices[indexCount++] = vertexIndex + (this._slices);
	                    vertexIndex++;
	                }
	            }
	        }
	        this._vertexBuffer = new VertexBuffer3D(vertices.length * 4, gl.STATIC_DRAW, false);
	        this._vertexBuffer.vertexDeclaration = vertexDeclaration;
	        this._indexBuffer = new IndexBuffer3D(IndexBuffer3D.INDEXTYPE_USHORT, indices.length, gl.STATIC_DRAW, false);
	        this._vertexBuffer.setData(vertices.buffer);
	        this._indexBuffer.setData(indices);
	        var bufferState = new BufferState();
	        bufferState.bind();
	        bufferState.applyVertexBuffer(this._vertexBuffer);
	        bufferState.applyIndexBuffer(this._indexBuffer);
	        bufferState.unBind();
	        this._bufferState = bufferState;
	    }
	    static __init__() {
	        SkyDome.instance = new SkyDome();
	    }
	    get stacks() {
	        return this._stacks;
	    }
	    get slices() {
	        return this._slices;
	    }
	    _render(state) {
	        var gl = Laya.LayaGL.instance;
	        var indexCount = this._indexBuffer.indexCount;
	        gl.drawElements(gl.TRIANGLES, indexCount, gl.UNSIGNED_SHORT, 0);
	        Laya.Stat.trianglesFaces += indexCount / 3;
	        Laya.Stat.renderBatches++;
	    }
	}
	SkyDome._radius = 1;

	class LightQueue {
	    constructor() {
	        this._length = 0;
	        this._elements = [];
	    }
	    add(light) {
	        if (this._length === this._elements.length)
	            this._elements.push(light);
	        else
	            this._elements[this._length] = light;
	        this._length++;
	    }
	    remove(light) {
	        var index = this._elements.indexOf(light);
	        this._length--;
	        if (index !== this._length) {
	            var end = this._elements[this._length];
	            this._elements[index] = end;
	        }
	    }
	    shift() {
	        this._length--;
	        return this._elements.shift();
	    }
	}
	class DirectionLightQueue extends LightQueue {
	    getSunLight() {
	        var maxIntIndex;
	        var maxIntensity = -1;
	        var elements = this._elements;
	        for (var i = 0; i < this._length; i++) {
	            var intensity = elements[i]._intensity;
	            if (maxIntensity < intensity) {
	                maxIntensity = intensity;
	                maxIntIndex = i;
	            }
	        }
	        return maxIntIndex;
	    }
	}
	class AlternateLightQueue extends LightQueue {
	    remove(light) {
	        var index = this._elements.indexOf(light);
	        this._elements.splice(index, 1);
	        this._length--;
	    }
	}

	class PixelLineFilter extends GeometryElement {
	    constructor(owner, maxLineCount) {
	        super();
	        this._floatCountPerVertices = 7;
	        this._minUpdate = Number.MAX_VALUE;
	        this._maxUpdate = Number.MIN_VALUE;
	        this._bufferState = new BufferState();
	        this._floatBound = new Float32Array(6);
	        this._calculateBound = false;
	        this._maxLineCount = 0;
	        this._lineCount = 0;
	        var pointCount = maxLineCount * 2;
	        this._owner = owner;
	        this._maxLineCount = maxLineCount;
	        this._vertices = new Float32Array(pointCount * this._floatCountPerVertices);
	        this._vertexBuffer = new VertexBuffer3D(PixelLineVertex.vertexDeclaration.vertexStride * pointCount, Laya.LayaGL.instance.STATIC_DRAW, false);
	        this._vertexBuffer.vertexDeclaration = PixelLineVertex.vertexDeclaration;
	        this._bufferState.bind();
	        this._bufferState.applyVertexBuffer(this._vertexBuffer);
	        this._bufferState.unBind();
	        var min = PixelLineFilter._tempVector0;
	        var max = PixelLineFilter._tempVector1;
	        min.setValue(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
	        max.setValue(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
	        this._bounds = new Bounds(min, max);
	    }
	    _getType() {
	        return PixelLineFilter._type;
	    }
	    _resizeLineData(maxCount) {
	        var pointCount = maxCount * 2;
	        var lastVertices = this._vertices;
	        this._vertexBuffer.destroy();
	        this._maxLineCount = maxCount;
	        var vertexCount = pointCount * this._floatCountPerVertices;
	        this._vertices = new Float32Array(vertexCount);
	        this._vertexBuffer = new VertexBuffer3D(PixelLineVertex.vertexDeclaration.vertexStride * pointCount, Laya.LayaGL.instance.STATIC_DRAW, false);
	        this._vertexBuffer.vertexDeclaration = PixelLineVertex.vertexDeclaration;
	        if (vertexCount < lastVertices.length) {
	            this._vertices.set(new Float32Array(lastVertices.buffer, 0, vertexCount));
	            this._vertexBuffer.setData(this._vertices.buffer, 0, 0, vertexCount * 4);
	        }
	        else {
	            this._vertices.set(lastVertices);
	            this._vertexBuffer.setData(this._vertices.buffer, 0, 0, lastVertices.length * 4);
	        }
	        this._bufferState.bind();
	        this._bufferState.applyVertexBuffer(this._vertexBuffer);
	        this._bufferState.unBind();
	    }
	    _updateLineVertices(offset, startPosition, endPosition, startColor, endColor) {
	        if (startPosition) {
	            this._vertices[offset + 0] = startPosition.x;
	            this._vertices[offset + 1] = startPosition.y;
	            this._vertices[offset + 2] = startPosition.z;
	        }
	        if (startColor) {
	            this._vertices[offset + 3] = startColor.r;
	            this._vertices[offset + 4] = startColor.g;
	            this._vertices[offset + 5] = startColor.b;
	            this._vertices[offset + 6] = startColor.a;
	        }
	        if (endPosition) {
	            this._vertices[offset + 7] = endPosition.x;
	            this._vertices[offset + 8] = endPosition.y;
	            this._vertices[offset + 9] = endPosition.z;
	        }
	        if (endColor) {
	            this._vertices[offset + 10] = endColor.r;
	            this._vertices[offset + 11] = endColor.g;
	            this._vertices[offset + 12] = endColor.b;
	            this._vertices[offset + 13] = endColor.a;
	        }
	        this._minUpdate = Math.min(this._minUpdate, offset);
	        this._maxUpdate = Math.max(this._maxUpdate, offset + this._floatCountPerVertices * 2);
	        var bounds = this._bounds;
	        var floatBound = this._floatBound;
	        var min = bounds.getMin(), max = bounds.getMax();
	        Vector3.min(min, startPosition, min);
	        Vector3.min(min, endPosition, min);
	        Vector3.max(max, startPosition, max);
	        Vector3.max(max, endPosition, max);
	        bounds.setMin(min);
	        bounds.setMax(max);
	        floatBound[0] = min.x, floatBound[1] = min.y, floatBound[2] = min.z;
	        floatBound[3] = max.x, floatBound[4] = max.y, floatBound[5] = max.z;
	    }
	    _reCalculateBound() {
	        if (this._calculateBound) {
	            var vertices = this._vertices;
	            var min = PixelLineFilter._tempVector0;
	            var max = PixelLineFilter._tempVector1;
	            min.setValue(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
	            max.setValue(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
	            for (var i = 0; i < this._lineCount * 2; ++i) {
	                var offset = this._floatCountPerVertices * i;
	                var x = vertices[offset + 0], y = vertices[offset + 1], z = vertices[offset + 2];
	                min.x = Math.min(x, min.x);
	                min.y = Math.min(y, min.y);
	                min.z = Math.min(z, min.z);
	                max.x = Math.max(x, max.x);
	                max.y = Math.max(y, max.y);
	                max.z = Math.max(z, max.z);
	            }
	            this._bounds.setMin(min);
	            this._bounds.setMax(max);
	            var floatBound = this._floatBound;
	            floatBound[0] = min.x, floatBound[1] = min.y, floatBound[2] = min.z;
	            floatBound[3] = max.x, floatBound[4] = max.y, floatBound[5] = max.z;
	            this._calculateBound = false;
	        }
	    }
	    _removeLineData(index) {
	        var floatCount = this._floatCountPerVertices * 2;
	        var nextIndex = index + 1;
	        var offset = index * floatCount;
	        var vertices = this._vertices;
	        var rightPartVertices = new Float32Array(vertices.buffer, nextIndex * floatCount * 4, (this._lineCount - nextIndex) * floatCount);
	        vertices.set(rightPartVertices, offset);
	        this._minUpdate = Math.min(this._minUpdate, offset);
	        this._maxUpdate = Math.max(this._maxUpdate, offset + rightPartVertices.length);
	        this._lineCount--;
	        var floatBound = this._floatBound;
	        var startX = vertices[offset], startY = vertices[offset + 1], startZ = vertices[offset + 2];
	        var endX = vertices[offset + 7], endY = vertices[offset + 8], endZ = vertices[offset + 9];
	        var minX = floatBound[0], minY = floatBound[1], minZ = floatBound[2];
	        var maxX = floatBound[3], maxY = floatBound[4], maxZ = floatBound[5];
	        if ((startX === minX) || (startX === maxX) || (startY === minY) || (startY === maxY) || (startZ === minZ) || (startZ === maxZ) ||
	            (endX === minX) || (endX === maxX) || (endY === minY) || (endY === maxY) || (endZ === minZ) || (endZ === maxZ))
	            this._calculateBound = true;
	    }
	    _updateLineData(index, startPosition, endPosition, startColor, endColor) {
	        var floatCount = this._floatCountPerVertices * 2;
	        this._updateLineVertices(index * floatCount, startPosition, endPosition, startColor, endColor);
	    }
	    _updateLineDatas(index, data) {
	        var floatCount = this._floatCountPerVertices * 2;
	        var count = data.length;
	        for (var i = 0; i < count; i++) {
	            var line = data[i];
	            this._updateLineVertices((index + i) * floatCount, line.startPosition, line.endPosition, line.startColor, line.endColor);
	        }
	    }
	    _getLineData(index, out) {
	        var startPosition = out.startPosition;
	        var startColor = out.startColor;
	        var endPosition = out.endPosition;
	        var endColor = out.endColor;
	        var vertices = this._vertices;
	        var offset = index * this._floatCountPerVertices * 2;
	        startPosition.x = vertices[offset + 0];
	        startPosition.y = vertices[offset + 1];
	        startPosition.z = vertices[offset + 2];
	        startColor.r = vertices[offset + 3];
	        startColor.g = vertices[offset + 4];
	        startColor.b = vertices[offset + 5];
	        startColor.a = vertices[offset + 6];
	        endPosition.x = vertices[offset + 7];
	        endPosition.y = vertices[offset + 8];
	        endPosition.z = vertices[offset + 9];
	        endColor.r = vertices[offset + 10];
	        endColor.g = vertices[offset + 11];
	        endColor.b = vertices[offset + 12];
	        endColor.a = vertices[offset + 13];
	    }
	    _prepareRender(state) {
	        return true;
	    }
	    _render(state) {
	        if (this._minUpdate !== Number.MAX_VALUE && this._maxUpdate !== Number.MIN_VALUE) {
	            this._vertexBuffer.setData(this._vertices.buffer, this._minUpdate * 4, this._minUpdate * 4, (this._maxUpdate - this._minUpdate) * 4);
	            this._minUpdate = Number.MAX_VALUE;
	            this._maxUpdate = Number.MIN_VALUE;
	        }
	        if (this._lineCount > 0) {
	            this._bufferState.bind();
	            var gl = Laya.LayaGL.instance;
	            gl.drawArrays(gl.LINES, 0, this._lineCount * 2);
	            Laya.Stat.renderBatches++;
	        }
	    }
	    destroy() {
	        if (this._destroyed)
	            return;
	        super.destroy();
	        this._bufferState.destroy();
	        this._vertexBuffer.destroy();
	        this._bufferState = null;
	        this._vertexBuffer = null;
	        this._vertices = null;
	    }
	}
	PixelLineFilter._tempVector0 = new Vector3();
	PixelLineFilter._tempVector1 = new Vector3();
	PixelLineFilter._type = GeometryElement._typeCounter++;

	class PixelLineRenderer extends BaseRender {
	    constructor(owner) {
	        super(owner);
	        this._projectionViewWorldMatrix = new Matrix4x4();
	    }
	    _calculateBoundingBox() {
	        var worldMat = this._owner.transform.worldMatrix;
	        var lineFilter = this._owner._geometryFilter;
	        lineFilter._reCalculateBound();
	        lineFilter._bounds._tranform(worldMat, this._bounds);
	        if (Laya.Render.supportWebGLPlusCulling) {
	            var min = this._bounds.getMin();
	            var max = this._bounds.getMax();
	            var buffer = FrustumCulling._cullingBuffer;
	            buffer[this._cullingBufferIndex + 1] = min.x;
	            buffer[this._cullingBufferIndex + 2] = min.y;
	            buffer[this._cullingBufferIndex + 3] = min.z;
	            buffer[this._cullingBufferIndex + 4] = max.x;
	            buffer[this._cullingBufferIndex + 5] = max.y;
	            buffer[this._cullingBufferIndex + 6] = max.z;
	        }
	    }
	    _renderUpdateWithCamera(context, transform) {
	        var projectionView = context.projectionViewMatrix;
	        var sv = this._shaderValues;
	        if (transform) {
	            var worldMat = transform.worldMatrix;
	            sv.setMatrix4x4(Sprite3D.WORLDMATRIX, worldMat);
	            Matrix4x4.multiply(projectionView, worldMat, this._projectionViewWorldMatrix);
	            sv.setMatrix4x4(Sprite3D.MVPMATRIX, this._projectionViewWorldMatrix);
	        }
	        else {
	            sv.setMatrix4x4(Sprite3D.WORLDMATRIX, Matrix4x4.DEFAULT);
	            sv.setMatrix4x4(Sprite3D.MVPMATRIX, projectionView);
	        }
	    }
	}

	class PixelLineSprite3D extends RenderableSprite3D {
	    get maxLineCount() {
	        return this._geometryFilter._maxLineCount;
	    }
	    set maxLineCount(value) {
	        this._geometryFilter._resizeLineData(value);
	        this._geometryFilter._lineCount = Math.min(this._geometryFilter._lineCount, value);
	    }
	    get lineCount() {
	        return this._geometryFilter._lineCount;
	    }
	    set lineCount(value) {
	        if (value > this.maxLineCount)
	            throw "PixelLineSprite3D: lineCount can't large than maxLineCount";
	        else
	            this._geometryFilter._lineCount = value;
	    }
	    get pixelLineRenderer() {
	        return this._render;
	    }
	    constructor(maxCount = 2, name = null) {
	        super(name);
	        this._geometryFilter = new PixelLineFilter(this, maxCount);
	        this._render = new PixelLineRenderer(this);
	        this._changeRenderObjects(this._render, 0, PixelLineMaterial.defaultMaterial);
	    }
	    _changeRenderObjects(sender, index, material) {
	        var renderObjects = this._render._renderElements;
	        (material) || (material = PixelLineMaterial.defaultMaterial);
	        var renderElement = renderObjects[index];
	        (renderElement) || (renderElement = renderObjects[index] = new RenderElement());
	        renderElement.setTransform(this._transform);
	        renderElement.setGeometry(this._geometryFilter);
	        renderElement.render = this._render;
	        renderElement.material = material;
	    }
	    addLine(startPosition, endPosition, startColor, endColor) {
	        if (this._geometryFilter._lineCount !== this._geometryFilter._maxLineCount)
	            this._geometryFilter._updateLineData(this._geometryFilter._lineCount++, startPosition, endPosition, startColor, endColor);
	        else
	            throw "PixelLineSprite3D: lineCount has equal with maxLineCount.";
	    }
	    addLines(lines) {
	        var lineCount = this._geometryFilter._lineCount;
	        var addCount = lines.length;
	        if (lineCount + addCount > this._geometryFilter._maxLineCount) {
	            throw "PixelLineSprite3D: lineCount plus lines count must less than maxLineCount.";
	        }
	        else {
	            this._geometryFilter._updateLineDatas(lineCount, lines);
	            this._geometryFilter._lineCount += addCount;
	        }
	    }
	    removeLine(index) {
	        if (index < this._geometryFilter._lineCount)
	            this._geometryFilter._removeLineData(index);
	        else
	            throw "PixelLineSprite3D: index must less than lineCount.";
	    }
	    setLine(index, startPosition, endPosition, startColor, endColor) {
	        if (index < this._geometryFilter._lineCount)
	            this._geometryFilter._updateLineData(index, startPosition, endPosition, startColor, endColor);
	        else
	            throw "PixelLineSprite3D: index must less than lineCount.";
	    }
	    getLine(index, out) {
	        if (index < this.lineCount)
	            this._geometryFilter._getLineData(index, out);
	        else
	            throw "PixelLineSprite3D: index must less than lineCount.";
	    }
	    clear() {
	        this._geometryFilter._lineCount = 0;
	    }
	    _create() {
	        return new PixelLineSprite3D();
	    }
	}

	class RenderQueue {
	    constructor(isTransparent = false) {
	        this.isTransparent = false;
	        this.elements = new SingletonList();
	        this.lastTransparentRenderElement = null;
	        this.lastTransparentBatched = false;
	        this.isTransparent = isTransparent;
	    }
	    _compare(left, right) {
	        var renderQueue = left.material.renderQueue - right.material.renderQueue;
	        if (renderQueue === 0) {
	            var sort = this.isTransparent ? right.render._distanceForSort - left.render._distanceForSort : left.render._distanceForSort - right.render._distanceForSort;
	            return sort + right.render.sortingFudge - left.render.sortingFudge;
	        }
	        else {
	            return renderQueue;
	        }
	    }
	    _partitionRenderObject(left, right) {
	        var elements = this.elements.elements;
	        var pivot = elements[Math.floor((right + left) / 2)];
	        while (left <= right) {
	            while (this._compare(elements[left], pivot) < 0)
	                left++;
	            while (this._compare(elements[right], pivot) > 0)
	                right--;
	            if (left < right) {
	                var temp = elements[left];
	                elements[left] = elements[right];
	                elements[right] = temp;
	                left++;
	                right--;
	            }
	            else if (left === right) {
	                left++;
	                break;
	            }
	        }
	        return left;
	    }
	    _quickSort(left, right) {
	        if (this.elements.length > 1) {
	            var index = this._partitionRenderObject(left, right);
	            var leftIndex = index - 1;
	            if (left < leftIndex)
	                this._quickSort(left, leftIndex);
	            if (index < right)
	                this._quickSort(index, right);
	        }
	    }
	    _render(context, isTarget) {
	        var elements = this.elements.elements;
	        for (var i = 0, n = this.elements.length; i < n; i++)
	            elements[i]._render(context, isTarget);
	    }
	    clear() {
	        this.elements.length = 0;
	        this.lastTransparentRenderElement = null;
	        this.lastTransparentBatched = false;
	    }
	}

	class BoundsOctreeNode {
	    constructor(octree, parent, baseLength, center) {
	        this._bounds = new BoundBox(new Vector3(), new Vector3());
	        this._objects = [];
	        this._isContaion = false;
	        this.center = new Vector3();
	        this.baseLength = 0.0;
	        this._setValues(octree, parent, baseLength, center);
	    }
	    static _encapsulates(outerBound, innerBound) {
	        return CollisionUtils.boxContainsBox(outerBound, innerBound) == ContainmentType.Contains;
	    }
	    _setValues(octree, parent, baseLength, center) {
	        this._octree = octree;
	        this._parent = parent;
	        this.baseLength = baseLength;
	        center.cloneTo(this.center);
	        var min = this._bounds.min;
	        var max = this._bounds.max;
	        var halfSize = (octree._looseness * baseLength) / 2;
	        min.setValue(center.x - halfSize, center.y - halfSize, center.z - halfSize);
	        max.setValue(center.x + halfSize, center.y + halfSize, center.z + halfSize);
	    }
	    _getChildBound(index) {
	        if (this._children != null && this._children[index]) {
	            return this._children[index]._bounds;
	        }
	        else {
	            var quarter = this.baseLength / 4;
	            var halfChildSize = ((this.baseLength / 2) * this._octree._looseness) / 2;
	            var bounds = BoundsOctreeNode._tempBoundBox;
	            var min = bounds.min;
	            var max = bounds.max;
	            switch (index) {
	                case 0:
	                    min.x = this.center.x - quarter - halfChildSize;
	                    min.y = this.center.y + quarter - halfChildSize;
	                    min.z = this.center.z - quarter - halfChildSize;
	                    max.x = this.center.x - quarter + halfChildSize;
	                    max.y = this.center.y + quarter + halfChildSize;
	                    max.z = this.center.z - quarter + halfChildSize;
	                    break;
	                case 1:
	                    min.x = this.center.x + quarter - halfChildSize;
	                    min.y = this.center.y + quarter - halfChildSize;
	                    min.z = this.center.z - quarter - halfChildSize;
	                    max.x = this.center.x + quarter + halfChildSize;
	                    max.y = this.center.y + quarter + halfChildSize;
	                    max.z = this.center.z - quarter + halfChildSize;
	                    break;
	                case 2:
	                    min.x = this.center.x - quarter - halfChildSize;
	                    min.y = this.center.y + quarter - halfChildSize;
	                    min.z = this.center.z + quarter - halfChildSize;
	                    max.x = this.center.x - quarter + halfChildSize;
	                    max.y = this.center.y + quarter + halfChildSize;
	                    max.z = this.center.z + quarter + halfChildSize;
	                    break;
	                case 3:
	                    min.x = this.center.x + quarter - halfChildSize;
	                    min.y = this.center.y + quarter - halfChildSize;
	                    min.z = this.center.z + quarter - halfChildSize;
	                    max.x = this.center.x + quarter + halfChildSize;
	                    max.y = this.center.y + quarter + halfChildSize;
	                    max.z = this.center.z + quarter + halfChildSize;
	                    break;
	                case 4:
	                    min.x = this.center.x - quarter - halfChildSize;
	                    min.y = this.center.y - quarter - halfChildSize;
	                    min.z = this.center.z - quarter - halfChildSize;
	                    max.x = this.center.x - quarter + halfChildSize;
	                    max.y = this.center.y - quarter + halfChildSize;
	                    max.z = this.center.z - quarter + halfChildSize;
	                    break;
	                case 5:
	                    min.x = this.center.x + quarter - halfChildSize;
	                    min.y = this.center.y - quarter - halfChildSize;
	                    min.z = this.center.z - quarter - halfChildSize;
	                    max.x = this.center.x + quarter + halfChildSize;
	                    max.y = this.center.y - quarter + halfChildSize;
	                    max.z = this.center.z - quarter + halfChildSize;
	                    break;
	                case 6:
	                    min.x = this.center.x - quarter - halfChildSize;
	                    min.y = this.center.y - quarter - halfChildSize;
	                    min.z = this.center.z + quarter - halfChildSize;
	                    max.x = this.center.x - quarter + halfChildSize;
	                    max.y = this.center.y - quarter + halfChildSize;
	                    max.z = this.center.z + quarter + halfChildSize;
	                    break;
	                case 7:
	                    min.x = this.center.x + quarter - halfChildSize;
	                    min.y = this.center.y - quarter - halfChildSize;
	                    min.z = this.center.z + quarter - halfChildSize;
	                    max.x = this.center.x + quarter + halfChildSize;
	                    max.y = this.center.y - quarter + halfChildSize;
	                    max.z = this.center.z + quarter + halfChildSize;
	                    break;
	                default:
	            }
	            return bounds;
	        }
	    }
	    _getChildCenter(index) {
	        if (this._children != null) {
	            return this._children[index].center;
	        }
	        else {
	            var quarter = this.baseLength / 4;
	            var childCenter = BoundsOctreeNode._tempVector30;
	            switch (index) {
	                case 0:
	                    childCenter.x = this.center.x - quarter;
	                    childCenter.y = this.center.y + quarter;
	                    childCenter.z = this.center.z - quarter;
	                    break;
	                case 1:
	                    childCenter.x = this.center.x + quarter;
	                    childCenter.y = this.center.y + quarter;
	                    childCenter.z = this.center.z - quarter;
	                    break;
	                case 2:
	                    childCenter.x = this.center.x - quarter;
	                    childCenter.y = this.center.y + quarter;
	                    childCenter.z = this.center.z + quarter;
	                    break;
	                case 3:
	                    childCenter.x = this.center.x + quarter;
	                    childCenter.y = this.center.y + quarter;
	                    childCenter.z = this.center.z + quarter;
	                    break;
	                case 4:
	                    childCenter.x = this.center.x - quarter;
	                    childCenter.y = this.center.y - quarter;
	                    childCenter.z = this.center.z - quarter;
	                    break;
	                case 5:
	                    childCenter.x = this.center.x + quarter;
	                    childCenter.y = this.center.y - quarter;
	                    childCenter.z = this.center.z - quarter;
	                    break;
	                case 6:
	                    childCenter.x = this.center.x - quarter;
	                    childCenter.y = this.center.y - quarter;
	                    childCenter.z = this.center.z + quarter;
	                    break;
	                case 7:
	                    childCenter.x = this.center.x + quarter;
	                    childCenter.y = this.center.y - quarter;
	                    childCenter.z = this.center.z + quarter;
	                    break;
	                default:
	            }
	            return childCenter;
	        }
	    }
	    _getChild(index) {
	        var quarter = this.baseLength / 4;
	        this._children || (this._children = []);
	        switch (index) {
	            case 0:
	                return this._children[0] || (this._children[0] = new BoundsOctreeNode(this._octree, this, this.baseLength / 2, new Vector3(this.center.x + -quarter, this.center.y + quarter, this.center.z - quarter)));
	            case 1:
	                return this._children[1] || (this._children[1] = new BoundsOctreeNode(this._octree, this, this.baseLength / 2, new Vector3(this.center.x + quarter, this.center.y + quarter, this.center.z - quarter)));
	            case 2:
	                return this._children[2] || (this._children[2] = new BoundsOctreeNode(this._octree, this, this.baseLength / 2, new Vector3(this.center.x - quarter, this.center.y + quarter, this.center.z + quarter)));
	            case 3:
	                return this._children[3] || (this._children[3] = new BoundsOctreeNode(this._octree, this, this.baseLength / 2, new Vector3(this.center.x + quarter, this.center.y + quarter, this.center.z + quarter)));
	            case 4:
	                return this._children[4] || (this._children[4] = new BoundsOctreeNode(this._octree, this, this.baseLength / 2, new Vector3(this.center.x - quarter, this.center.y - quarter, this.center.z - quarter)));
	            case 5:
	                return this._children[5] || (this._children[5] = new BoundsOctreeNode(this._octree, this, this.baseLength / 2, new Vector3(this.center.x + quarter, this.center.y - quarter, this.center.z - quarter)));
	            case 6:
	                return this._children[6] || (this._children[6] = new BoundsOctreeNode(this._octree, this, this.baseLength / 2, new Vector3(this.center.x - quarter, this.center.y - quarter, this.center.z + quarter)));
	            case 7:
	                return this._children[7] || (this._children[7] = new BoundsOctreeNode(this._octree, this, this.baseLength / 2, new Vector3(this.center.x + quarter, this.center.y - quarter, this.center.z + quarter)));
	            default:
	                throw "BoundsOctreeNode: unknown index.";
	        }
	    }
	    _shouldMerge() {
	        var objectCount = this._objects.length;
	        for (var i = 0; i < 8; i++) {
	            var child = this._children[i];
	            if (child) {
	                if (child._children != null)
	                    return false;
	                objectCount += child._objects.length;
	            }
	        }
	        return objectCount <= BoundsOctreeNode._NUM_OBJECTS_ALLOWED;
	    }
	    _mergeChildren() {
	        for (var i = 0; i < 8; i++) {
	            var child = this._children[i];
	            if (child) {
	                child._parent = null;
	                var childObjects = child._objects;
	                for (var j = childObjects.length - 1; j >= 0; j--) {
	                    var childObject = childObjects[j];
	                    this._objects.push(childObject);
	                    childObject._setOctreeNode(this);
	                }
	            }
	        }
	        this._children = null;
	    }
	    _merge() {
	        if (this._children === null) {
	            var parent = this._parent;
	            if (parent && parent._shouldMerge()) {
	                parent._mergeChildren();
	                parent._merge();
	            }
	        }
	    }
	    _checkAddNode(object) {
	        if (this._children == null) {
	            if (this._objects.length < BoundsOctreeNode._NUM_OBJECTS_ALLOWED || (this.baseLength / 2) < this._octree._minSize) {
	                return this;
	            }
	            for (var i = this._objects.length - 1; i >= 0; i--) {
	                var existObject = this._objects[i];
	                var fitChildIndex = this._bestFitChild(existObject.bounds.getCenter());
	                if (BoundsOctreeNode._encapsulates(this._getChildBound(fitChildIndex), existObject.bounds._getBoundBox())) {
	                    this._objects.splice(this._objects.indexOf(existObject), 1);
	                    this._getChild(fitChildIndex)._add(existObject);
	                }
	            }
	        }
	        var newFitChildIndex = this._bestFitChild(object.bounds.getCenter());
	        if (BoundsOctreeNode._encapsulates(this._getChildBound(newFitChildIndex), object.bounds._getBoundBox()))
	            return this._getChild(newFitChildIndex)._checkAddNode(object);
	        else
	            return this;
	    }
	    _add(object) {
	        var addNode = this._checkAddNode(object);
	        addNode._objects.push(object);
	        object._setOctreeNode(addNode);
	    }
	    _remove(object) {
	        var index = this._objects.indexOf(object);
	        this._objects.splice(index, 1);
	        object._setOctreeNode(null);
	        this._merge();
	    }
	    _addUp(object) {
	        if ((CollisionUtils.boxContainsBox(this._bounds, object.bounds._getBoundBox()) === ContainmentType.Contains)) {
	            this._add(object);
	            return true;
	        }
	        else {
	            if (this._parent)
	                return this._parent._addUp(object);
	            else
	                return false;
	        }
	    }
	    _getCollidingWithFrustum(context, frustum, testVisible, camPos, customShader, replacementTag) {
	        if (testVisible) {
	            var type = frustum.containsBoundBox(this._bounds);
	            Laya.Stat.octreeNodeCulling++;
	            if (type === ContainmentType.Disjoint)
	                return;
	            testVisible = (type === ContainmentType.Intersects);
	        }
	        this._isContaion = !testVisible;
	        var camera = context.camera;
	        var scene = context.scene;
	        for (var i = 0, n = this._objects.length; i < n; i++) {
	            var render = this._objects[i];
	            if (camera._isLayerVisible(render._owner.layer) && render._enable) {
	                if (testVisible) {
	                    Laya.Stat.frustumCulling++;
	                    if (!render._needRender(frustum, context))
	                        continue;
	                }
	                render._distanceForSort = Vector3.distance(render.bounds.getCenter(), camPos);
	                var elements = render._renderElements;
	                for (var j = 0, m = elements.length; j < m; j++) {
	                    var element = elements[j];
	                    element._update(scene, context, customShader, replacementTag);
	                }
	            }
	        }
	        if (this._children != null) {
	            for (i = 0; i < 8; i++) {
	                var child = this._children[i];
	                child && child._getCollidingWithFrustum(context, frustum, testVisible, camPos, customShader, replacementTag);
	            }
	        }
	    }
	    _getCollidingWithBoundBox(checkBound, testVisible, result) {
	        if (testVisible) {
	            var type = CollisionUtils.boxContainsBox(this._bounds, checkBound);
	            if (type === ContainmentType.Disjoint)
	                return;
	            testVisible = (type === ContainmentType.Intersects);
	        }
	        if (testVisible) {
	            for (var i = 0, n = this._objects.length; i < n; i++) {
	                var object = this._objects[i];
	                if (CollisionUtils.intersectsBoxAndBox(object.bounds._getBoundBox(), checkBound)) {
	                    result.push(object);
	                }
	            }
	        }
	        if (this._children != null) {
	            for (i = 0; i < 8; i++) {
	                var child = this._children[i];
	                child._getCollidingWithBoundBox(checkBound, testVisible, result);
	            }
	        }
	    }
	    _bestFitChild(boundCenter) {
	        return (boundCenter.x <= this.center.x ? 0 : 1) + (boundCenter.y >= this.center.y ? 0 : 4) + (boundCenter.z <= this.center.z ? 0 : 2);
	    }
	    _update(object) {
	        if (CollisionUtils.boxContainsBox(this._bounds, object.bounds._getBoundBox()) === ContainmentType.Contains) {
	            var addNode = this._checkAddNode(object);
	            if (addNode !== object._getOctreeNode()) {
	                addNode._objects.push(object);
	                object._setOctreeNode(addNode);
	                var index = this._objects.indexOf(object);
	                this._objects.splice(index, 1);
	                this._merge();
	            }
	            return true;
	        }
	        else {
	            if (this._parent) {
	                var sucess = this._parent._addUp(object);
	                if (sucess) {
	                    index = this._objects.indexOf(object);
	                    this._objects.splice(index, 1);
	                    this._merge();
	                }
	                return sucess;
	            }
	            else {
	                return false;
	            }
	        }
	    }
	    add(object) {
	        if (!BoundsOctreeNode._encapsulates(this._bounds, object.bounds._getBoundBox()))
	            return false;
	        this._add(object);
	        return true;
	    }
	    remove(object) {
	        if (object._getOctreeNode() !== this)
	            return false;
	        this._remove(object);
	        return true;
	    }
	    update(object) {
	        if (object._getOctreeNode() !== this)
	            return false;
	        return this._update(object);
	    }
	    shrinkIfPossible(minLength) {
	        if (this.baseLength < minLength * 2)
	            return this;
	        var bestFit = -1;
	        for (var i = 0, n = this._objects.length; i < n; i++) {
	            var object = this._objects[i];
	            var newBestFit = this._bestFitChild(object.bounds.getCenter());
	            if (i == 0 || newBestFit == bestFit) {
	                var childBounds = this._getChildBound(newBestFit);
	                if (BoundsOctreeNode._encapsulates(childBounds, object.bounds._getBoundBox()))
	                    (i == 0) && (bestFit = newBestFit);
	                else
	                    return this;
	            }
	            else {
	                return this;
	            }
	        }
	        if (this._children != null) {
	            var childHadContent = false;
	            for (i = 0, n = this._children.length; i < n; i++) {
	                var child = this._children[i];
	                if (child && child.hasAnyObjects()) {
	                    if (childHadContent)
	                        return this;
	                    if (bestFit >= 0 && bestFit != i)
	                        return this;
	                    childHadContent = true;
	                    bestFit = i;
	                }
	            }
	        }
	        else {
	            if (bestFit != -1) {
	                var childCenter = this._getChildCenter(bestFit);
	                this._setValues(this._octree, null, this.baseLength / 2, childCenter);
	            }
	            return this;
	        }
	        if (bestFit != -1) {
	            var newRoot = this._children[bestFit];
	            newRoot._parent = null;
	            return newRoot;
	        }
	        else {
	            return this;
	        }
	    }
	    hasAnyObjects() {
	        if (this._objects.length > 0)
	            return true;
	        if (this._children != null) {
	            for (var i = 0; i < 8; i++) {
	                var child = this._children[i];
	                if (child && child.hasAnyObjects())
	                    return true;
	            }
	        }
	        return false;
	    }
	    getCollidingWithBoundBox(checkBound, result) {
	        this._getCollidingWithBoundBox(checkBound, true, result);
	    }
	    getCollidingWithRay(ray, result, maxDistance = Number.MAX_VALUE) {
	        var distance = CollisionUtils.intersectsRayAndBoxRD(ray, this._bounds);
	        if (distance == -1 || distance > maxDistance)
	            return;
	        for (var i = 0, n = this._objects.length; i < n; i++) {
	            var object = this._objects[i];
	            distance = CollisionUtils.intersectsRayAndBoxRD(ray, object.bounds._getBoundBox());
	            if (distance !== -1 && distance <= maxDistance)
	                result.push(object);
	        }
	        if (this._children != null) {
	            for (i = 0; i < 8; i++) {
	                var child = this._children[i];
	                child.getCollidingWithRay(ray, result, maxDistance);
	            }
	        }
	    }
	    getCollidingWithFrustum(context, customShader, replacementTag) {
	        var cameraPos = context.camera.transform.position;
	        var boundFrustum = context.camera.boundFrustum;
	        this._getCollidingWithFrustum(context, boundFrustum, true, cameraPos, customShader, replacementTag);
	    }
	    isCollidingWithBoundBox(checkBound) {
	        if (!(CollisionUtils.intersectsBoxAndBox(this._bounds, checkBound)))
	            return false;
	        for (var i = 0, n = this._objects.length; i < n; i++) {
	            var object = this._objects[i];
	            if (CollisionUtils.intersectsBoxAndBox(object.bounds._getBoundBox(), checkBound))
	                return true;
	        }
	        if (this._children != null) {
	            for (i = 0; i < 8; i++) {
	                var child = this._children[i];
	                if (child.isCollidingWithBoundBox(checkBound))
	                    return true;
	            }
	        }
	        return false;
	    }
	    isCollidingWithRay(ray, maxDistance = Number.MAX_VALUE) {
	        var distance = CollisionUtils.intersectsRayAndBoxRD(ray, this._bounds);
	        if (distance == -1 || distance > maxDistance)
	            return false;
	        for (var i = 0, n = this._objects.length; i < n; i++) {
	            var object = this._objects[i];
	            distance = CollisionUtils.intersectsRayAndBoxRD(ray, object.bounds._getBoundBox());
	            if (distance !== -1 && distance <= maxDistance)
	                return true;
	        }
	        if (this._children != null) {
	            for (i = 0; i < 8; i++) {
	                var child = this._children[i];
	                if (child.isCollidingWithRay(ray, maxDistance))
	                    return true;
	            }
	        }
	        return false;
	    }
	    getBound() {
	        return this._bounds;
	    }
	    drawAllBounds(debugLine, currentDepth, maxDepth) {
	        if (this._children === null && this._objects.length == 0)
	            return;
	        currentDepth++;
	        var color = BoundsOctreeNode._tempColor0;
	        if (this._isContaion) {
	            color.r = 0.0;
	            color.g = 0.0;
	            color.b = 1.0;
	        }
	        else {
	            var tint = maxDepth ? currentDepth / maxDepth : 0;
	            color.r = 1.0 - tint;
	            color.g = tint;
	            color.b = 0.0;
	        }
	        color.a = 0.3;
	        Utils3D._drawBound(debugLine, this._bounds, color);
	        if (this._children != null) {
	            for (var i = 0; i < 8; i++) {
	                var child = this._children[i];
	                child && child.drawAllBounds(debugLine, currentDepth, maxDepth);
	            }
	        }
	    }
	    drawAllObjects(debugLine, currentDepth, maxDepth) {
	        currentDepth++;
	        var color = BoundsOctreeNode._tempColor0;
	        if (this._isContaion) {
	            color.r = 0.0;
	            color.g = 0.0;
	            color.b = 1.0;
	        }
	        else {
	            var tint = maxDepth ? currentDepth / maxDepth : 0;
	            color.r = 1.0 - tint;
	            color.g = tint;
	            color.b = 0.0;
	        }
	        color.a = 1.0;
	        for (var i = 0, n = this._objects.length; i < n; i++)
	            Utils3D._drawBound(debugLine, this._objects[i].bounds._getBoundBox(), color);
	        if (this._children != null) {
	            for (i = 0; i < 8; i++) {
	                var child = this._children[i];
	                child && child.drawAllObjects(debugLine, currentDepth, maxDepth);
	            }
	        }
	    }
	}
	BoundsOctreeNode._tempVector3 = new Vector3();
	BoundsOctreeNode._tempVector30 = new Vector3();
	BoundsOctreeNode._tempVector31 = new Vector3();
	BoundsOctreeNode._tempColor0 = new Color();
	BoundsOctreeNode._tempBoundBox = new BoundBox(new Vector3(), new Vector3());
	BoundsOctreeNode._NUM_OBJECTS_ALLOWED = 8;

	class OctreeMotionList extends SingletonList {
	    constructor() {
	        super();
	    }
	    add(element) {
	        var index = element._getIndexInMotionList();
	        if (index !== -1)
	            throw "OctreeMotionList:element has  in  PhysicsUpdateList.";
	        this._add(element);
	        element._setIndexInMotionList(this.length++);
	    }
	    remove(element) {
	        var index = element._getIndexInMotionList();
	        this.length--;
	        if (index !== this.length) {
	            var end = this.elements[this.length];
	            this.elements[index] = end;
	            end._setIndexInMotionList(index);
	        }
	        element._setIndexInMotionList(-1);
	    }
	}

	class BoundsOctree {
	    constructor(initialWorldSize, initialWorldPos, minNodeSize, looseness) {
	        this._motionObjects = new OctreeMotionList();
	        this.count = 0;
	        if (minNodeSize > initialWorldSize) {
	            console.warn("Minimum node size must be at least as big as the initial world size. Was: " + minNodeSize + " Adjusted to: " + initialWorldSize);
	            minNodeSize = initialWorldSize;
	        }
	        this._initialSize = initialWorldSize;
	        this._minSize = minNodeSize;
	        this._looseness = Math.min(Math.max(looseness, 1.0), 2.0);
	        this._rootNode = new BoundsOctreeNode(this, null, initialWorldSize, initialWorldPos);
	    }
	    _getMaxDepth(node, depth) {
	        depth++;
	        var children = node._children;
	        if (children != null) {
	            var curDepth = depth;
	            for (var i = 0, n = children.length; i < n; i++) {
	                var child = children[i];
	                child && (depth = Math.max(this._getMaxDepth(child, curDepth), depth));
	            }
	        }
	        return depth;
	    }
	    _grow(growObjectCenter) {
	        var xDirection = growObjectCenter.x >= 0 ? 1 : -1;
	        var yDirection = growObjectCenter.y >= 0 ? 1 : -1;
	        var zDirection = growObjectCenter.z >= 0 ? 1 : -1;
	        var oldRoot = this._rootNode;
	        var half = this._rootNode.baseLength / 2;
	        var newLength = this._rootNode.baseLength * 2;
	        var rootCenter = this._rootNode.center;
	        var newCenter = new Vector3(rootCenter.x + xDirection * half, rootCenter.y + yDirection * half, rootCenter.z + zDirection * half);
	        this._rootNode = new BoundsOctreeNode(this, null, newLength, newCenter);
	        if (oldRoot.hasAnyObjects()) {
	            var rootPos = this._rootNode._bestFitChild(oldRoot.center);
	            var children = [];
	            for (var i = 0; i < 8; i++) {
	                if (i == rootPos) {
	                    oldRoot._parent = this._rootNode;
	                    children[i] = oldRoot;
	                }
	            }
	            this._rootNode._children = children;
	        }
	    }
	    add(object) {
	        var count = 0;
	        while (!this._rootNode.add(object)) {
	            var growCenter = BoundsOctree._tempVector30;
	            Vector3.subtract(object.bounds.getCenter(), this._rootNode.center, growCenter);
	            this._grow(growCenter);
	            if (++count > 20) {
	                throw "Aborted Add operation as it seemed to be going on forever (" + (count - 1) + ") attempts at growing the octree.";
	            }
	        }
	        this.count++;
	    }
	    remove(object) {
	        var removed = object._getOctreeNode().remove(object);
	        if (removed) {
	            this.count--;
	        }
	        return removed;
	    }
	    update(object) {
	        var count = 0;
	        var octreeNode = object._getOctreeNode();
	        if (octreeNode) {
	            while (!octreeNode._update(object)) {
	                var growCenter = BoundsOctree._tempVector30;
	                Vector3.subtract(object.bounds.getCenter(), this._rootNode.center, growCenter);
	                this._grow(growCenter);
	                if (++count > 20) {
	                    throw "Aborted Add operation as it seemed to be going on forever (" + (count - 1) + ") attempts at growing the octree.";
	                }
	            }
	            return true;
	        }
	        else {
	            return false;
	        }
	    }
	    shrinkRootIfPossible() {
	        this._rootNode = this._rootNode.shrinkIfPossible(this._initialSize);
	    }
	    addMotionObject(object) {
	        this._motionObjects.add(object);
	    }
	    removeMotionObject(object) {
	        this._motionObjects.remove(object);
	    }
	    updateMotionObjects() {
	        var elements = this._motionObjects.elements;
	        for (var i = 0, n = this._motionObjects.length; i < n; i++) {
	            var object = elements[i];
	            this.update(object);
	            object._setIndexInMotionList(-1);
	        }
	        this._motionObjects.length = 0;
	    }
	    isCollidingWithBoundBox(checkBounds) {
	        return this._rootNode.isCollidingWithBoundBox(checkBounds);
	    }
	    isCollidingWithRay(ray, maxDistance = Number.MAX_VALUE) {
	        return this._rootNode.isCollidingWithRay(ray, maxDistance);
	    }
	    getCollidingWithBoundBox(checkBound, result) {
	        this._rootNode.getCollidingWithBoundBox(checkBound, result);
	    }
	    getCollidingWithRay(ray, result, maxDistance = Number.MAX_VALUE) {
	        this._rootNode.getCollidingWithRay(ray, result, maxDistance);
	    }
	    getCollidingWithFrustum(context, shader, replacementTag) {
	        this._rootNode.getCollidingWithFrustum(context, shader, replacementTag);
	    }
	    getMaxBounds() {
	        return this._rootNode.getBound();
	    }
	    drawAllBounds(pixelLine) {
	        var maxDepth = this._getMaxDepth(this._rootNode, -1);
	        this._rootNode.drawAllBounds(pixelLine, -1, maxDepth);
	    }
	    drawAllObjects(pixelLine) {
	        var maxDepth = this._getMaxDepth(this._rootNode, -1);
	        this._rootNode.drawAllObjects(pixelLine, -1, maxDepth);
	    }
	}
	BoundsOctree._tempVector30 = new Vector3();

	class Scene3D extends Laya.Sprite {
	    constructor() {
	        super();
	        this._lightCount = 0;
	        this._pointLights = new LightQueue();
	        this._spotLights = new LightQueue();
	        this._directionLights = new DirectionLightQueue();
	        this._alternateLights = new AlternateLightQueue();
	        this._lightmaps = [];
	        this._skyRenderer = new SkyRenderer();
	        this._reflectionMode = 1;
	        this._input = new Input3D();
	        this._timer = Laya.ILaya.timer;
	        this._collsionTestList = [];
	        this._renders = new SimpleSingletonList();
	        this._opaqueQueue = new RenderQueue(false);
	        this._transparentQueue = new RenderQueue(true);
	        this._cameraPool = [];
	        this._animatorPool = new SimpleSingletonList();
	        this._scriptPool = new Array();
	        this._tempScriptPool = new Array();
	        this._needClearScriptPool = false;
	        this._castShadowRenders = new CastShadowList();
	        this.currentCreationLayer = Math.pow(2, 0);
	        this.enableLight = true;
	        this._key = new Laya.SubmitKey();
	        this._time = 0;
	        this._pickIdToSprite = new Object();
	        if (Physics3D._enbalePhysics)
	            this._physicsSimulation = new PhysicsSimulation(Scene3D.physicsSettings);
	        this._shaderValues = new ShaderData(null);
	        this.parallelSplitShadowMaps = [];
	        this.enableFog = false;
	        this.fogStart = 300;
	        this.fogRange = 1000;
	        this.fogColor = new Vector3(0.7, 0.7, 0.7);
	        this.ambientColor = new Vector3(0.212, 0.227, 0.259);
	        this.reflectionIntensity = 1.0;
	        (Laya.WebGL.shaderHighPrecision) && (this._shaderValues.addDefine(Shader3D.SHADERDEFINE_HIGHPRECISION));
	        (Config3D._config._multiLighting) || (this._shaderValues.addDefine(Shader3D.SHADERDEFINE_LEGACYSINGALLIGHTING));
	        if (Laya.Render.supportWebGLPlusCulling) {
	            this._cullingBufferIndices = new Int32Array(1024);
	            this._cullingBufferResult = new Int32Array(1024);
	        }
	        this._scene = this;
	        this._input.__init__(Laya.Render.canvas, this);
	        if (Scene3D.octreeCulling) {
	            this._octree = new BoundsOctree(Scene3D.octreeInitialSize, Scene3D.octreeInitialCenter, Scene3D.octreeMinNodeSize, Scene3D.octreeLooseness);
	        }
	        if (FrustumCulling.debugFrustumCulling) {
	            this._debugTool = new PixelLineSprite3D();
	            var lineMaterial = new PixelLineMaterial();
	            lineMaterial.renderQueue = BaseMaterial.RENDERQUEUE_TRANSPARENT;
	            lineMaterial.alphaTest = false;
	            lineMaterial.depthWrite = false;
	            lineMaterial.cull = RenderState.CULL_BACK;
	            lineMaterial.blend = RenderState.BLEND_ENABLE_ALL;
	            lineMaterial.blendSrc = RenderState.BLENDPARAM_SRC_ALPHA;
	            lineMaterial.blendDst = RenderState.BLENDPARAM_ONE_MINUS_SRC_ALPHA;
	            lineMaterial.depthTest = RenderState.DEPTHTEST_LESS;
	            this._debugTool.pixelLineRenderer.sharedMaterial = lineMaterial;
	        }
	    }
	    static __init__() {
	        var con = Config3D._config;
	        var multiLighting = con._multiLighting;
	        if (multiLighting) {
	            const width = 4;
	            var maxLightCount = con.maxLightCount;
	            var clusterSlices = con.lightClusterCount;
	            Cluster.instance = new Cluster(clusterSlices.x, clusterSlices.y, clusterSlices.z, Math.min(con.maxLightCount, con._maxAreaLightCountPerClusterAverage));
	            Scene3D._lightTexture = Utils3D._createFloatTextureBuffer(width, maxLightCount);
	            Scene3D._lightTexture.lock = true;
	            Scene3D._lightPixles = new Float32Array(maxLightCount * width * 4);
	        }
	        Scene3DShaderDeclaration.SHADERDEFINE_FOG = Shader3D.getDefineByName("FOG");
	        Scene3DShaderDeclaration.SHADERDEFINE_DIRECTIONLIGHT = Shader3D.getDefineByName("DIRECTIONLIGHT");
	        Scene3DShaderDeclaration.SHADERDEFINE_POINTLIGHT = Shader3D.getDefineByName("POINTLIGHT");
	        Scene3DShaderDeclaration.SHADERDEFINE_SPOTLIGHT = Shader3D.getDefineByName("SPOTLIGHT");
	        Scene3DShaderDeclaration.SHADERDEFINE_CAST_SHADOW = Shader3D.getDefineByName("CASTSHADOW");
	        Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_PSSM1 = Shader3D.getDefineByName("SHADOWMAP_PSSM1");
	        Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_PSSM2 = Shader3D.getDefineByName("SHADOWMAP_PSSM2");
	        Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_PSSM3 = Shader3D.getDefineByName("SHADOWMAP_PSSM3");
	        Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_PCF_NO = Shader3D.getDefineByName("SHADOWMAP_PCF_NO");
	        Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_PCF1 = Shader3D.getDefineByName("SHADOWMAP_PCF1");
	        Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_PCF2 = Shader3D.getDefineByName("SHADOWMAP_PCF2");
	        Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_PCF3 = Shader3D.getDefineByName("SHADOWMAP_PCF3");
	        Scene3DShaderDeclaration.SHADERDEFINE_REFLECTMAP = Shader3D.getDefineByName("REFLECTMAP");
	    }
	    static load(url, complete) {
	        Laya.ILaya.loader.create(url, complete, null, Scene3D.HIERARCHY);
	    }
	    _allotPickColorByID(id, pickColor) {
	        var pickColorR = Math.floor(id / (255 * 255));
	        id -= pickColorR * 255 * 255;
	        var pickColorG = Math.floor(id / 255);
	        id -= pickColorG * 255;
	        var pickColorB = id;
	        pickColor.x = pickColorR / 255;
	        pickColor.y = pickColorG / 255;
	        pickColor.z = pickColorB / 255;
	        pickColor.w = 1.0;
	    }
	    _searchIDByPickColor(pickColor) {
	        var id = pickColor.x * 255 * 255 + pickColor.y * 255 + pickColor.z;
	        return id;
	    }
	    get url() {
	        return this._url;
	    }
	    get enableFog() {
	        return this._enableFog;
	    }
	    set enableFog(value) {
	        if (this._enableFog !== value) {
	            this._enableFog = value;
	            if (value) {
	                this._shaderValues.addDefine(Scene3DShaderDeclaration.SHADERDEFINE_FOG);
	            }
	            else
	                this._shaderValues.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_FOG);
	        }
	    }
	    get fogColor() {
	        return this._shaderValues.getVector3(Scene3D.FOGCOLOR);
	    }
	    set fogColor(value) {
	        this._shaderValues.setVector3(Scene3D.FOGCOLOR, value);
	    }
	    get fogStart() {
	        return this._shaderValues.getNumber(Scene3D.FOGSTART);
	    }
	    set fogStart(value) {
	        this._shaderValues.setNumber(Scene3D.FOGSTART, value);
	    }
	    get fogRange() {
	        return this._shaderValues.getNumber(Scene3D.FOGRANGE);
	    }
	    set fogRange(value) {
	        this._shaderValues.setNumber(Scene3D.FOGRANGE, value);
	    }
	    get ambientColor() {
	        return this._shaderValues.getVector3(Scene3D.AMBIENTCOLOR);
	    }
	    set ambientColor(value) {
	        this._shaderValues.setVector3(Scene3D.AMBIENTCOLOR, value);
	    }
	    get skyRenderer() {
	        return this._skyRenderer;
	    }
	    get customReflection() {
	        return this._shaderValues.getTexture(Scene3D.REFLECTIONTEXTURE);
	    }
	    set customReflection(value) {
	        this._shaderValues.setTexture(Scene3D.REFLECTIONTEXTURE, value);
	        if (value)
	            this._shaderValues.addDefine(Scene3DShaderDeclaration.SHADERDEFINE_REFLECTMAP);
	        else
	            this._shaderValues.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_REFLECTMAP);
	    }
	    get reflectionIntensity() {
	        return this._shaderValues.getNumber(Scene3D.REFLETIONINTENSITY);
	    }
	    set reflectionIntensity(value) {
	        value = Math.max(Math.min(value, 1.0), 0.0);
	        this._shaderValues.setNumber(Scene3D.REFLETIONINTENSITY, value);
	    }
	    get physicsSimulation() {
	        return this._physicsSimulation;
	    }
	    get reflectionMode() {
	        return this._reflectionMode;
	    }
	    set reflectionMode(value) {
	        this._reflectionMode = value;
	    }
	    get timer() {
	        return this._timer;
	    }
	    set timer(value) {
	        this._timer = value;
	    }
	    get input() {
	        return this._input;
	    }
	    _setLightmapToChildNode(sprite) {
	        if (sprite instanceof RenderableSprite3D)
	            sprite._render._applyLightMapParams();
	        var children = sprite._children;
	        for (var i = 0, n = children.length; i < n; i++)
	            this._setLightmapToChildNode(children[i]);
	    }
	    _update() {
	        var delta = this.timer._delta / 1000;
	        this._time += delta;
	        this._shaderValues.setNumber(Scene3D.TIME, this._time);
	        var simulation = this._physicsSimulation;
	        if (Physics3D._enbalePhysics && !PhysicsSimulation.disableSimulation) {
	            simulation._updatePhysicsTransformFromRender();
	            PhysicsComponent._addUpdateList = false;
	            simulation._simulate(delta);
	            simulation._updateCharacters();
	            PhysicsComponent._addUpdateList = true;
	            simulation._updateCollisions();
	            simulation._eventScripts();
	        }
	        this._input._update();
	        this._clearScript();
	        this._updateScript();
	        Animator._update(this);
	        this._lateUpdateScript();
	    }
	    _binarySearchIndexInCameraPool(camera) {
	        var start = 0;
	        var end = this._cameraPool.length - 1;
	        var mid;
	        while (start <= end) {
	            mid = Math.floor((start + end) / 2);
	            var midValue = this._cameraPool[mid]._renderingOrder;
	            if (midValue == camera._renderingOrder)
	                return mid;
	            else if (midValue > camera._renderingOrder)
	                end = mid - 1;
	            else
	                start = mid + 1;
	        }
	        return start;
	    }
	    onEnable() {
	        this._input._onCanvasEvent(Laya.Render.canvas);
	    }
	    onDisable() {
	        this._input._offCanvasEvent(Laya.Render.canvas);
	    }
	    _setCreateURL(url) {
	        this._url = Laya.URL.formatURL(url);
	    }
	    _getGroup() {
	        return this._group;
	    }
	    _setGroup(value) {
	        this._group = value;
	    }
	    _clearScript() {
	        if (this._needClearScriptPool) {
	            var scripts = this._scriptPool;
	            for (var i = 0, n = scripts.length; i < n; i++) {
	                var script = scripts[i];
	                if (script) {
	                    script._indexInPool = this._tempScriptPool.length;
	                    this._tempScriptPool.push(script);
	                }
	            }
	            this._scriptPool = this._tempScriptPool;
	            scripts.length = 0;
	            this._tempScriptPool = scripts;
	            this._needClearScriptPool = false;
	        }
	    }
	    _updateScript() {
	        var scripts = this._scriptPool;
	        for (var i = 0, n = scripts.length; i < n; i++) {
	            var script = scripts[i];
	            (script && script.enabled) && (script.onUpdate());
	        }
	    }
	    _lateUpdateScript() {
	        var scripts = this._scriptPool;
	        for (var i = 0, n = scripts.length; i < n; i++) {
	            var script = scripts[i];
	            (script && script.enabled) && (script.onLateUpdate());
	        }
	    }
	    _addScript(script) {
	        var scripts = this._scriptPool;
	        script._indexInPool = scripts.length;
	        scripts.push(script);
	    }
	    _removeScript(script) {
	        this._scriptPool[script._indexInPool] = null;
	        script._indexInPool = -1;
	        this._needClearScriptPool = true;
	    }
	    _preRenderScript() {
	        var scripts = this._scriptPool;
	        for (var i = 0, n = scripts.length; i < n; i++) {
	            var script = scripts[i];
	            (script && script.enabled) && (script.onPreRender());
	        }
	    }
	    _postRenderScript() {
	        var scripts = this._scriptPool;
	        for (var i = 0, n = scripts.length; i < n; i++) {
	            var script = scripts[i];
	            (script && script.enabled) && (script.onPostRender());
	        }
	    }
	    _prepareSceneToRender() {
	        var shaderValues = this._shaderValues;
	        var multiLighting = Config3D._config._multiLighting;
	        if (multiLighting) {
	            var ligTex = Scene3D._lightTexture;
	            var ligPix = Scene3D._lightPixles;
	            const pixelWidth = ligTex.width;
	            const floatWidth = pixelWidth * 4;
	            var curCount = 0;
	            var dirCount = this._directionLights._length;
	            var dirElements = this._directionLights._elements;
	            if (dirCount > 0) {
	                var sunLightIndex = this._directionLights.getSunLight();
	                for (var i = 0; i < dirCount; i++, curCount++) {
	                    var dirLight = dirElements[i];
	                    var dir = dirLight._direction;
	                    var intCor = dirLight._intensityColor;
	                    var off = floatWidth * curCount;
	                    Vector3.scale(dirLight.color, dirLight._intensity, intCor);
	                    dirLight.transform.worldMatrix.getForward(dir);
	                    Vector3.normalize(dir, dir);
	                    ligPix[off] = intCor.x;
	                    ligPix[off + 1] = intCor.y;
	                    ligPix[off + 2] = intCor.z;
	                    ligPix[off + 4] = dir.x;
	                    ligPix[off + 5] = dir.y;
	                    ligPix[off + 6] = dir.z;
	                    if (i == sunLightIndex) {
	                        shaderValues.setVector3(Scene3D.SUNLIGHTDIRCOLOR, intCor);
	                        shaderValues.setVector3(Scene3D.SUNLIGHTDIRECTION, dir);
	                    }
	                }
	                shaderValues.addDefine(Scene3DShaderDeclaration.SHADERDEFINE_DIRECTIONLIGHT);
	            }
	            else {
	                shaderValues.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_DIRECTIONLIGHT);
	            }
	            var poiCount = this._pointLights._length;
	            if (poiCount > 0) {
	                var poiElements = this._pointLights._elements;
	                for (var i = 0; i < poiCount; i++, curCount++) {
	                    var poiLight = poiElements[i];
	                    var pos = poiLight.transform.position;
	                    var intCor = poiLight._intensityColor;
	                    var off = floatWidth * curCount;
	                    Vector3.scale(poiLight.color, poiLight._intensity, intCor);
	                    ligPix[off] = intCor.x;
	                    ligPix[off + 1] = intCor.y;
	                    ligPix[off + 2] = intCor.z;
	                    ligPix[off + 3] = poiLight.range;
	                    ligPix[off + 4] = pos.x;
	                    ligPix[off + 5] = pos.y;
	                    ligPix[off + 6] = pos.z;
	                }
	                shaderValues.addDefine(Scene3DShaderDeclaration.SHADERDEFINE_POINTLIGHT);
	            }
	            else {
	                shaderValues.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_POINTLIGHT);
	            }
	            var spoCount = this._spotLights._length;
	            if (spoCount > 0) {
	                var spoElements = this._spotLights._elements;
	                for (var i = 0; i < spoCount; i++, curCount++) {
	                    var spoLight = spoElements[i];
	                    var dir = spoLight._direction;
	                    var pos = spoLight.transform.position;
	                    var intCor = spoLight._intensityColor;
	                    var off = floatWidth * curCount;
	                    Vector3.scale(spoLight.color, spoLight._intensity, intCor);
	                    spoLight.transform.worldMatrix.getForward(dir);
	                    Vector3.normalize(dir, dir);
	                    ligPix[off] = intCor.x;
	                    ligPix[off + 1] = intCor.y;
	                    ligPix[off + 2] = intCor.z;
	                    ligPix[off + 3] = spoLight.range;
	                    ligPix[off + 4] = pos.x;
	                    ligPix[off + 5] = pos.y;
	                    ligPix[off + 6] = pos.z;
	                    ligPix[off + 7] = spoLight.spotAngle * Math.PI / 180;
	                    ligPix[off + 8] = dir.x;
	                    ligPix[off + 9] = dir.y;
	                    ligPix[off + 10] = dir.z;
	                }
	                shaderValues.addDefine(Scene3DShaderDeclaration.SHADERDEFINE_SPOTLIGHT);
	            }
	            else {
	                shaderValues.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_SPOTLIGHT);
	            }
	            (curCount > 0) && (ligTex.setSubPixels(0, 0, pixelWidth, curCount, ligPix, 0));
	            shaderValues.setTexture(Scene3D.LIGHTBUFFER, ligTex);
	            shaderValues.setInt(Scene3D.DIRECTIONLIGHTCOUNT, this._directionLights._length);
	            shaderValues.setTexture(Scene3D.CLUSTERBUFFER, Cluster.instance._clusterTexture);
	        }
	        else {
	            if (this._directionLights._length > 0) {
	                var dirLight = this._directionLights._elements[0];
	                Vector3.scale(dirLight.color, dirLight._intensity, dirLight._intensityColor);
	                dirLight.transform.worldMatrix.getForward(dirLight._direction);
	                Vector3.normalize(dirLight._direction, dirLight._direction);
	                shaderValues.setVector3(Scene3D.LIGHTDIRCOLOR, dirLight._intensityColor);
	                shaderValues.setVector3(Scene3D.LIGHTDIRECTION, dirLight._direction);
	                shaderValues.setVector3(Scene3D.SUNLIGHTDIRCOLOR, dirLight._intensityColor);
	                shaderValues.setVector3(Scene3D.SUNLIGHTDIRECTION, dirLight._direction);
	                shaderValues.addDefine(Scene3DShaderDeclaration.SHADERDEFINE_DIRECTIONLIGHT);
	            }
	            else {
	                shaderValues.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_DIRECTIONLIGHT);
	            }
	            if (this._pointLights._length > 0) {
	                var poiLight = this._pointLights._elements[0];
	                Vector3.scale(poiLight.color, poiLight._intensity, poiLight._intensityColor);
	                shaderValues.setVector3(Scene3D.POINTLIGHTCOLOR, poiLight._intensityColor);
	                shaderValues.setVector3(Scene3D.POINTLIGHTPOS, poiLight.transform.position);
	                shaderValues.setNumber(Scene3D.POINTLIGHTRANGE, poiLight.range);
	                shaderValues.addDefine(Scene3DShaderDeclaration.SHADERDEFINE_POINTLIGHT);
	            }
	            else {
	                shaderValues.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_POINTLIGHT);
	            }
	            if (this._spotLights._length > 0) {
	                var spotLight = this._spotLights._elements[0];
	                Vector3.scale(spotLight.color, spotLight._intensity, spotLight._intensityColor);
	                shaderValues.setVector3(Scene3D.SPOTLIGHTCOLOR, spotLight._intensityColor);
	                shaderValues.setVector3(Scene3D.SPOTLIGHTPOS, spotLight.transform.position);
	                spotLight.transform.worldMatrix.getForward(spotLight._direction);
	                Vector3.normalize(spotLight._direction, spotLight._direction);
	                shaderValues.setVector3(Scene3D.SPOTLIGHTDIRECTION, spotLight._direction);
	                shaderValues.setNumber(Scene3D.SPOTLIGHTRANGE, spotLight.range);
	                shaderValues.setNumber(Scene3D.SPOTLIGHTSPOTANGLE, spotLight.spotAngle * Math.PI / 180);
	                shaderValues.addDefine(Scene3DShaderDeclaration.SHADERDEFINE_SPOTLIGHT);
	            }
	            else {
	                shaderValues.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_SPOTLIGHT);
	            }
	        }
	    }
	    _addCamera(camera) {
	        var index = this._binarySearchIndexInCameraPool(camera);
	        var order = camera._renderingOrder;
	        var count = this._cameraPool.length;
	        while (index < count && this._cameraPool[index]._renderingOrder <= order)
	            index++;
	        this._cameraPool.splice(index, 0, camera);
	    }
	    _removeCamera(camera) {
	        this._cameraPool.splice(this._cameraPool.indexOf(camera), 1);
	    }
	    _preCulling(context, camera, shader, replacementTag) {
	        FrustumCulling.renderObjectCulling(camera, this, context, this._renders, shader, replacementTag);
	    }
	    _clear(gl, state) {
	        var viewport = state.viewport;
	        var camera = state.camera;
	        var renderTexture = camera._getInternalRenderTexture();
	        var vpW = viewport.width;
	        var vpH = viewport.height;
	        var vpX = viewport.x;
	        var vpY = camera._getCanvasHeight() - viewport.y - vpH;
	        gl.viewport(vpX, vpY, vpW, vpH);
	        var flag;
	        var clearFlag = camera.clearFlag;
	        if (clearFlag === BaseCamera.CLEARFLAG_SKY && !(camera.skyRenderer._isAvailable() || this._skyRenderer._isAvailable()))
	            clearFlag = BaseCamera.CLEARFLAG_SOLIDCOLOR;
	        switch (clearFlag) {
	            case BaseCamera.CLEARFLAG_SOLIDCOLOR:
	                var clearColor = camera.clearColor;
	                gl.enable(gl.SCISSOR_TEST);
	                gl.scissor(vpX, vpY, vpW, vpH);
	                if (clearColor)
	                    gl.clearColor(clearColor.x, clearColor.y, clearColor.z, clearColor.w);
	                else
	                    gl.clearColor(0, 0, 0, 0);
	                if (renderTexture) {
	                    flag = gl.COLOR_BUFFER_BIT;
	                    switch (renderTexture.depthStencilFormat) {
	                        case Laya.RenderTextureDepthFormat.DEPTH_16:
	                            flag |= gl.DEPTH_BUFFER_BIT;
	                            break;
	                        case Laya.RenderTextureDepthFormat.STENCIL_8:
	                            flag |= gl.STENCIL_BUFFER_BIT;
	                            break;
	                        case Laya.RenderTextureDepthFormat.DEPTHSTENCIL_16_8:
	                            flag |= gl.DEPTH_BUFFER_BIT;
	                            flag |= gl.STENCIL_BUFFER_BIT;
	                            break;
	                    }
	                }
	                else {
	                    flag = gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT;
	                }
	                Laya.WebGLContext.setDepthMask(gl, true);
	                gl.clear(flag);
	                gl.disable(gl.SCISSOR_TEST);
	                break;
	            case BaseCamera.CLEARFLAG_SKY:
	            case BaseCamera.CLEARFLAG_DEPTHONLY:
	                gl.enable(gl.SCISSOR_TEST);
	                gl.scissor(vpX, vpY, vpW, vpH);
	                if (renderTexture) {
	                    switch (renderTexture.depthStencilFormat) {
	                        case Laya.RenderTextureDepthFormat.DEPTH_16:
	                            flag = gl.DEPTH_BUFFER_BIT;
	                            break;
	                        case Laya.RenderTextureDepthFormat.STENCIL_8:
	                            flag = gl.STENCIL_BUFFER_BIT;
	                            break;
	                        case Laya.RenderTextureDepthFormat.DEPTHSTENCIL_16_8:
	                            flag = gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT;
	                            break;
	                    }
	                }
	                else {
	                    flag = gl.DEPTH_BUFFER_BIT;
	                }
	                Laya.WebGLContext.setDepthMask(gl, true);
	                gl.clear(flag);
	                gl.disable(gl.SCISSOR_TEST);
	                break;
	            case BaseCamera.CLEARFLAG_NONE:
	                break;
	            default:
	                throw new Error("BaseScene:camera clearFlag invalid.");
	        }
	    }
	    _renderScene(context) {
	        var camera = context.camera;
	        var renderTar = camera._getInternalRenderTexture();
	        renderTar ? this._opaqueQueue._render(context, true) : this._opaqueQueue._render(context, false);
	        if (camera.clearFlag === BaseCamera.CLEARFLAG_SKY) {
	            if (camera.skyRenderer._isAvailable())
	                camera.skyRenderer._render(context);
	            else if (this._skyRenderer._isAvailable())
	                this._skyRenderer._render(context);
	        }
	        renderTar ? this._transparentQueue._render(context, true) : this._transparentQueue._render(context, false);
	        if (FrustumCulling.debugFrustumCulling) {
	            var renderElements = this._debugTool._render._renderElements;
	            for (var i = 0, n = renderElements.length; i < n; i++) {
	                renderElements[i]._update(this, context, null, null);
	                renderElements[i]._render(context, false);
	            }
	        }
	    }
	    _parse(data, spriteMap) {
	        var lightMapsData = data.lightmaps;
	        if (lightMapsData) {
	            var lightMapCount = lightMapsData.length;
	            var lightmaps = [];
	            for (var i = 0; i < lightMapCount; i++)
	                lightmaps[i] = Laya.Loader.getRes(lightMapsData[i].path);
	            this.setlightmaps(lightmaps);
	        }
	        var ambientColorData = data.ambientColor;
	        if (ambientColorData) {
	            var ambCol = this.ambientColor;
	            ambCol.fromArray(ambientColorData);
	            this.ambientColor = ambCol;
	        }
	        var skyData = data.sky;
	        if (skyData) {
	            this._skyRenderer.material = Laya.Loader.getRes(skyData.material.path);
	            switch (skyData.mesh) {
	                case "SkyBox":
	                    this._skyRenderer.mesh = SkyBox.instance;
	                    break;
	                case "SkyDome":
	                    this._skyRenderer.mesh = SkyDome.instance;
	                    break;
	                default:
	                    this.skyRenderer.mesh = SkyBox.instance;
	            }
	        }
	        var reflectionTextureData = data.reflectionTexture;
	        reflectionTextureData && (this.customReflection = Laya.Loader.getRes(reflectionTextureData));
	        this.enableFog = data.enableFog;
	        this.fogStart = data.fogStart;
	        this.fogRange = data.fogRange;
	        var fogColorData = data.fogColor;
	        if (fogColorData) {
	            var fogCol = this.fogColor;
	            fogCol.fromArray(fogColorData);
	            this.fogColor = fogCol;
	        }
	    }
	    _onActive() {
	        super._onActive();
	        Laya.ILaya.stage._scene3Ds.push(this);
	    }
	    _onInActive() {
	        super._onInActive();
	        var scenes = Laya.ILaya.stage._scene3Ds;
	        scenes.splice(scenes.indexOf(this), 1);
	    }
	    _addRenderObject(render) {
	        if (this._octree && render._supportOctree) {
	            this._octree.add(render);
	        }
	        else {
	            this._renders.add(render);
	            if (Laya.Render.supportWebGLPlusCulling) {
	                var indexInList = render._getIndexInList();
	                var length = this._cullingBufferIndices.length;
	                if (indexInList >= length) {
	                    var tempIndices = this._cullingBufferIndices;
	                    var tempResult = this._cullingBufferResult;
	                    this._cullingBufferIndices = new Int32Array(length + 1024);
	                    this._cullingBufferResult = new Int32Array(length + 1024);
	                    this._cullingBufferIndices.set(tempIndices, 0);
	                    this._cullingBufferResult.set(tempResult, 0);
	                }
	                this._cullingBufferIndices[indexInList] = render._cullingBufferIndex;
	            }
	        }
	    }
	    _removeRenderObject(render) {
	        if (this._octree && render._supportOctree) {
	            this._octree.remove(render);
	        }
	        else {
	            var endRender;
	            if (Laya.Render.supportWebGLPlusCulling) {
	                endRender = this._renders.elements[this._renders.length - 1];
	            }
	            this._renders.remove(render);
	            if (Laya.Render.supportWebGLPlusCulling) {
	                this._cullingBufferIndices[endRender._getIndexInList()] = endRender._cullingBufferIndex;
	            }
	        }
	    }
	    _addShadowCastRenderObject(render) {
	        if (this._octree) ;
	        else {
	            this._castShadowRenders.add(render);
	        }
	    }
	    _removeShadowCastRenderObject(render) {
	        if (this._octree) ;
	        else {
	            this._castShadowRenders.remove(render);
	        }
	    }
	    _getRenderQueue(index) {
	        if (index <= 2500)
	            return this._opaqueQueue;
	        else
	            return this._transparentQueue;
	    }
	    setlightmaps(value) {
	        var maps = this._lightmaps;
	        for (var i = 0, n = maps.length; i < n; i++)
	            maps[i]._removeReference();
	        if (value) {
	            var count = value.length;
	            maps.length = count;
	            for (i = 0; i < count; i++) {
	                var lightMap = value[i];
	                lightMap._addReference();
	                maps[i] = lightMap;
	            }
	        }
	        else {
	            throw new Error("Scene3D: value value can't be null.");
	        }
	        for (i = 0, n = this._children.length; i < n; i++)
	            this._setLightmapToChildNode(this._children[i]);
	    }
	    getlightmaps() {
	        return this._lightmaps.slice();
	    }
	    destroy(destroyChild = true) {
	        if (this.destroyed)
	            return;
	        super.destroy(destroyChild);
	        this._skyRenderer.destroy();
	        this._skyRenderer = null;
	        this._directionLights = null;
	        this._pointLights = null;
	        this._spotLights = null;
	        this._alternateLights = null;
	        this._lightmaps = null;
	        this._shaderValues = null;
	        this._renders = null;
	        this._castShadowRenders = null;
	        this._cameraPool = null;
	        this._octree = null;
	        this.parallelSplitShadowMaps = null;
	        this._physicsSimulation && this._physicsSimulation._destroy();
	        Laya.Loader.clearRes(this.url);
	    }
	    render(ctx, x, y) {
	        ctx._curSubmit = Laya.SubmitBase.RENDERBASE;
	        this._children.length > 0 && ctx.addRenderObject(this);
	    }
	    renderSubmit() {
	        var gl = Laya.LayaGL.instance;
	        this._prepareSceneToRender();
	        var i, n, n1;
	        for (i = 0, n = this._cameraPool.length, n1 = n - 1; i < n; i++) {
	            if (Laya.Render.supportWebGLPlusRendering)
	                ShaderData.setRuntimeValueMode((i == n1) ? true : false);
	            var camera = this._cameraPool[i];
	            camera.enableRender && camera.render();
	        }
	        Laya.Context.set2DRenderConfig();
	        return 1;
	    }
	    getRenderType() {
	        return 0;
	    }
	    releaseRender() {
	    }
	    reUse(context, pos) {
	        return 0;
	    }
	}
	Scene3D.HIERARCHY = "HIERARCHY";
	Scene3D.physicsSettings = new PhysicsSettings();
	Scene3D.octreeCulling = false;
	Scene3D.octreeInitialSize = 64.0;
	Scene3D.octreeInitialCenter = new Vector3(0, 0, 0);
	Scene3D.octreeMinNodeSize = 2.0;
	Scene3D.octreeLooseness = 1.25;
	Scene3D.REFLECTIONMODE_SKYBOX = 0;
	Scene3D.REFLECTIONMODE_CUSTOM = 1;
	Scene3D.FOGCOLOR = Shader3D.propertyNameToID("u_FogColor");
	Scene3D.FOGSTART = Shader3D.propertyNameToID("u_FogStart");
	Scene3D.FOGRANGE = Shader3D.propertyNameToID("u_FogRange");
	Scene3D.DIRECTIONLIGHTCOUNT = Shader3D.propertyNameToID("u_DirationLightCount");
	Scene3D.LIGHTBUFFER = Shader3D.propertyNameToID("u_LightBuffer");
	Scene3D.CLUSTERBUFFER = Shader3D.propertyNameToID("u_LightClusterBuffer");
	Scene3D.SUNLIGHTDIRECTION = Shader3D.propertyNameToID("u_SunLight.direction");
	Scene3D.SUNLIGHTDIRCOLOR = Shader3D.propertyNameToID("u_SunLight.color");
	Scene3D.LIGHTDIRECTION = Shader3D.propertyNameToID("u_DirectionLight.direction");
	Scene3D.LIGHTDIRCOLOR = Shader3D.propertyNameToID("u_DirectionLight.color");
	Scene3D.POINTLIGHTPOS = Shader3D.propertyNameToID("u_PointLight.position");
	Scene3D.POINTLIGHTRANGE = Shader3D.propertyNameToID("u_PointLight.range");
	Scene3D.POINTLIGHTATTENUATION = Shader3D.propertyNameToID("u_PointLight.attenuation");
	Scene3D.POINTLIGHTCOLOR = Shader3D.propertyNameToID("u_PointLight.color");
	Scene3D.SPOTLIGHTPOS = Shader3D.propertyNameToID("u_SpotLight.position");
	Scene3D.SPOTLIGHTDIRECTION = Shader3D.propertyNameToID("u_SpotLight.direction");
	Scene3D.SPOTLIGHTSPOTANGLE = Shader3D.propertyNameToID("u_SpotLight.spot");
	Scene3D.SPOTLIGHTRANGE = Shader3D.propertyNameToID("u_SpotLight.range");
	Scene3D.SPOTLIGHTCOLOR = Shader3D.propertyNameToID("u_SpotLight.color");
	Scene3D.SHADOWDISTANCE = Shader3D.propertyNameToID("u_shadowPSSMDistance");
	Scene3D.SHADOWLIGHTVIEWPROJECT = Shader3D.propertyNameToID("u_lightShadowVP");
	Scene3D.SHADOWMAPPCFOFFSET = Shader3D.propertyNameToID("u_shadowPCFoffset");
	Scene3D.SHADOWMAPTEXTURE1 = Shader3D.propertyNameToID("u_shadowMap1");
	Scene3D.SHADOWMAPTEXTURE2 = Shader3D.propertyNameToID("u_shadowMap2");
	Scene3D.SHADOWMAPTEXTURE3 = Shader3D.propertyNameToID("u_shadowMap3");
	Scene3D.AMBIENTCOLOR = Shader3D.propertyNameToID("u_AmbientColor");
	Scene3D.REFLECTIONTEXTURE = Shader3D.propertyNameToID("u_ReflectTexture");
	Scene3D.REFLETIONINTENSITY = Shader3D.propertyNameToID("u_ReflectIntensity");
	Scene3D.TIME = Shader3D.propertyNameToID("u_Time");

	class SkinnedMeshSprite3DShaderDeclaration {
	}

	class SkinnedMeshRenderer extends MeshRenderer {
	    constructor(owner) {
	        super(owner);
	        this._bones = [];
	        this._skinnedDataLoopMarks = [];
	        this._localBounds = new Bounds(Vector3._ZERO, Vector3._ZERO);
	        this._cacheAnimationNode = [];
	    }
	    get localBounds() {
	        return this._localBounds;
	    }
	    set localBounds(value) {
	        this._localBounds = value;
	    }
	    get rootBone() {
	        return this._cacheRootBone;
	    }
	    set rootBone(value) {
	        if (this._cacheRootBone != value) {
	            if (this._cacheRootBone)
	                this._cacheRootBone.transform.off(Laya.Event.TRANSFORM_CHANGED, this, this._onWorldMatNeedChange);
	            else
	                this._owner.transform.off(Laya.Event.TRANSFORM_CHANGED, this, this._onWorldMatNeedChange);
	            if (value)
	                value.transform.on(Laya.Event.TRANSFORM_CHANGED, this, this._onWorldMatNeedChange);
	            else
	                this._owner.transform.on(Laya.Event.TRANSFORM_CHANGED, this, this._onWorldMatNeedChange);
	            this._cacheRootBone = value;
	            this._onWorldMatNeedChange(Transform3D.TRANSFORM_WORLDPOSITION | Transform3D.TRANSFORM_WORLDQUATERNION | Transform3D.TRANSFORM_WORLDSCALE);
	        }
	    }
	    get bones() {
	        return this._bones;
	    }
	    _computeSkinnedData() {
	        if (this._cacheMesh && this._cacheAvatar || this._cacheMesh && !this._cacheAvatar) {
	            var bindPoses = this._cacheMesh._inverseBindPoses;
	            var meshBindPoseIndices = this._cacheMesh._bindPoseIndices;
	            var pathMarks = this._cacheMesh._skinDataPathMarks;
	            for (var i = 0, n = this._cacheMesh.subMeshCount; i < n; i++) {
	                var subMeshBoneIndices = this._cacheMesh.getSubMesh(i)._boneIndicesList;
	                var subData = this._skinnedData[i];
	                for (var j = 0, m = subMeshBoneIndices.length; j < m; j++) {
	                    var boneIndices = subMeshBoneIndices[j];
	                    this._computeSubSkinnedData(bindPoses, boneIndices, meshBindPoseIndices, subData[j], pathMarks);
	                }
	            }
	        }
	    }
	    _computeSubSkinnedData(bindPoses, boneIndices, meshBindPoseInices, data, pathMarks) {
	        for (var k = 0, q = boneIndices.length; k < q; k++) {
	            var index = boneIndices[k];
	            if (this._skinnedDataLoopMarks[index] === Laya.Stat.loopCount) {
	                var p = pathMarks[index];
	                var preData = this._skinnedData[p[0]][p[1]];
	                var srcIndex = p[2] * 16;
	                var dstIndex = k * 16;
	                for (var d = 0; d < 16; d++)
	                    data[dstIndex + d] = preData[srcIndex + d];
	            }
	            else {
	                if (!this._cacheAvatar) {
	                    var boneIndex = meshBindPoseInices[index];
	                    Utils3D._mulMatrixArray(this._bones[boneIndex].transform.worldMatrix.elements, bindPoses[boneIndex], data, k * 16);
	                }
	                else {
	                    Utils3D._mulMatrixArray(this._cacheAnimationNode[index].transform.getWorldMatrix(), bindPoses[meshBindPoseInices[index]], data, k * 16);
	                }
	                this._skinnedDataLoopMarks[index] = Laya.Stat.loopCount;
	            }
	        }
	    }
	    _onWorldMatNeedChange(flag) {
	        this._boundsChange = true;
	        if (this._octreeNode) {
	            if (this._cacheAvatar) {
	                if (this._indexInOctreeMotionList === -1)
	                    this._octreeNode._octree.addMotionObject(this);
	            }
	            else {
	                flag &= Transform3D.TRANSFORM_WORLDPOSITION | Transform3D.TRANSFORM_WORLDQUATERNION | Transform3D.TRANSFORM_WORLDSCALE;
	                if (flag) {
	                    if (this._indexInOctreeMotionList === -1)
	                        this._octreeNode._octree.addMotionObject(this);
	                }
	            }
	        }
	    }
	    _createRenderElement() {
	        return new RenderElement();
	    }
	    _onMeshChange(value) {
	        super._onMeshChange(value);
	        this._cacheMesh = value;
	        var subMeshCount = value.subMeshCount;
	        this._skinnedData = [];
	        this._skinnedDataLoopMarks.length = value._bindPoseIndices.length;
	        for (var i = 0; i < subMeshCount; i++) {
	            var subBoneIndices = value.getSubMesh(i)._boneIndicesList;
	            var subCount = subBoneIndices.length;
	            var subData = this._skinnedData[i] = [];
	            for (var j = 0; j < subCount; j++)
	                subData[j] = new Float32Array(subBoneIndices[j].length * 16);
	        }
	        (this._cacheAvatar && value) && (this._getCacheAnimationNodes());
	    }
	    _setCacheAnimator(animator) {
	        this._cacheAnimator = animator;
	        this._shaderValues.addDefine(SkinnedMeshSprite3DShaderDeclaration.SHADERDEFINE_BONE);
	        this._setRootNode();
	    }
	    _calculateBoundingBox() {
	        if (!this._cacheAvatar) {
	            if (this._cacheRootBone)
	                this._localBounds._tranform(this._cacheRootBone.transform.worldMatrix, this._bounds);
	            else
	                this._localBounds._tranform(this._owner.transform.worldMatrix, this._bounds);
	        }
	        else {
	            if (this._cacheAnimator && this._rootBone) {
	                var worldMat = SkinnedMeshRenderer._tempMatrix4x4;
	                Utils3D.matrix4x4MultiplyMFM(this._cacheAnimator.owner.transform.worldMatrix, this._cacheRootAnimationNode.transform.getWorldMatrix(), worldMat);
	                this._localBounds._tranform(worldMat, this._bounds);
	            }
	            else {
	                super._calculateBoundingBox();
	            }
	        }
	        if (Laya.Render.supportWebGLPlusCulling) {
	            var min = this._bounds.getMin();
	            var max = this._bounds.getMax();
	            var buffer = FrustumCulling._cullingBuffer;
	            buffer[this._cullingBufferIndex + 1] = min.x;
	            buffer[this._cullingBufferIndex + 2] = min.y;
	            buffer[this._cullingBufferIndex + 3] = min.z;
	            buffer[this._cullingBufferIndex + 4] = max.x;
	            buffer[this._cullingBufferIndex + 5] = max.y;
	            buffer[this._cullingBufferIndex + 6] = max.z;
	        }
	    }
	    _renderUpdate(context, transform) {
	        if (this._cacheAnimator) {
	            this._computeSkinnedData();
	            if (!this._cacheAvatar) {
	                this._shaderValues.setMatrix4x4(Sprite3D.WORLDMATRIX, Matrix4x4.DEFAULT);
	            }
	            else {
	                var aniOwnerTrans = this._cacheAnimator.owner._transform;
	                this._shaderValues.setMatrix4x4(Sprite3D.WORLDMATRIX, aniOwnerTrans.worldMatrix);
	            }
	        }
	        else {
	            this._shaderValues.setMatrix4x4(Sprite3D.WORLDMATRIX, transform.worldMatrix);
	        }
	    }
	    _renderUpdateWithCamera(context, transform) {
	        var projectionView = context.projectionViewMatrix;
	        if (this._cacheAnimator) {
	            if (!this._cacheAvatar) {
	                this._shaderValues.setMatrix4x4(Sprite3D.MVPMATRIX, projectionView);
	            }
	            else {
	                var aniOwnerTrans = this._cacheAnimator.owner._transform;
	                Matrix4x4.multiply(projectionView, aniOwnerTrans.worldMatrix, this._projectionViewWorldMatrix);
	                this._shaderValues.setMatrix4x4(Sprite3D.MVPMATRIX, this._projectionViewWorldMatrix);
	            }
	        }
	        else {
	            Matrix4x4.multiply(projectionView, transform.worldMatrix, this._projectionViewWorldMatrix);
	            this._shaderValues.setMatrix4x4(Sprite3D.MVPMATRIX, this._projectionViewWorldMatrix);
	        }
	    }
	    _destroy() {
	        super._destroy();
	        if (!this._cacheAvatar) {
	            if (this._cacheRootBone)
	                (!this._cacheRootBone.destroyed) && (this._cacheRootBone.transform.off(Laya.Event.TRANSFORM_CHANGED, this, this._onWorldMatNeedChange));
	            else
	                (this._owner && !this._owner.destroyed) && (this._owner.transform.off(Laya.Event.TRANSFORM_CHANGED, this, this._onWorldMatNeedChange));
	        }
	        else {
	            if (this._cacheRootAnimationNode)
	                this._cacheRootAnimationNode.transform.off(Laya.Event.TRANSFORM_CHANGED, this, this._onWorldMatNeedChange);
	        }
	    }
	    get bounds() {
	        if (this._boundsChange || this._cacheAvatar) {
	            this._calculateBoundingBox();
	            this._boundsChange = false;
	        }
	        return this._bounds;
	    }
	    _setRootBone(name) {
	        this._rootBone = name;
	        this._setRootNode();
	    }
	    _setRootNode() {
	        var rootNode;
	        if (this._cacheAnimator && this._rootBone && this._cacheAvatar)
	            rootNode = this._cacheAnimator._avatarNodeMap[this._rootBone];
	        else
	            rootNode = null;
	        if (this._cacheRootAnimationNode != rootNode) {
	            this._onWorldMatNeedChange(Transform3D.TRANSFORM_WORLDPOSITION | Transform3D.TRANSFORM_WORLDQUATERNION | Transform3D.TRANSFORM_WORLDSCALE);
	            this._owner.transform.off(Laya.Event.TRANSFORM_CHANGED, this, this._onWorldMatNeedChange);
	            if (this._cacheRootAnimationNode)
	                this._cacheRootAnimationNode.transform.off(Laya.Event.TRANSFORM_CHANGED, this, this._onWorldMatNeedChange);
	            (rootNode) && (rootNode.transform.on(Laya.Event.TRANSFORM_CHANGED, this, this._onWorldMatNeedChange));
	            this._cacheRootAnimationNode = rootNode;
	        }
	    }
	    _getCacheAnimationNodes() {
	        var meshBoneNames = this._cacheMesh._boneNames;
	        var bindPoseIndices = this._cacheMesh._bindPoseIndices;
	        var innerBindPoseCount = bindPoseIndices.length;
	        if (!Laya.Render.supportWebGLPlusAnimation) {
	            this._cacheAnimationNode.length = innerBindPoseCount;
	            var nodeMap = this._cacheAnimator._avatarNodeMap;
	            for (var i = 0; i < innerBindPoseCount; i++) {
	                var node = nodeMap[meshBoneNames[bindPoseIndices[i]]];
	                this._cacheAnimationNode[i] = node;
	            }
	        }
	        else {
	            this._cacheAnimationNodeIndices = new Uint16Array(innerBindPoseCount);
	            var nodeMapC = this._cacheAnimator._avatarNodeMap;
	            for (i = 0; i < innerBindPoseCount; i++) {
	                var nodeC = nodeMapC[meshBoneNames[bindPoseIndices[i]]];
	                this._cacheAnimationNodeIndices[i] = nodeC ? nodeC._worldMatrixIndex : 0;
	            }
	        }
	    }
	    _setCacheAvatar(value) {
	        if (this._cacheAvatar !== value) {
	            if (this._cacheMesh) {
	                this._cacheAvatar = value;
	                if (value) {
	                    this._shaderValues.addDefine(SkinnedMeshSprite3DShaderDeclaration.SHADERDEFINE_BONE);
	                    this._getCacheAnimationNodes();
	                }
	            }
	            else {
	                this._cacheAvatar = value;
	            }
	            this._setRootNode();
	        }
	    }
	    _computeSubSkinnedDataNative(worldMatrixs, cacheAnimationNodeIndices, inverseBindPosesBuffer, boneIndices, bindPoseInices, data) {
	        Laya.LayaGL.instance.computeSubSkinnedData(worldMatrixs, cacheAnimationNodeIndices, inverseBindPosesBuffer, boneIndices, bindPoseInices, data);
	    }
	    _computeSkinnedDataForNative() {
	        if (this._cacheMesh && this._cacheAvatar || this._cacheMesh && !this._cacheAvatar) {
	            var bindPoses = this._cacheMesh._inverseBindPoses;
	            var meshBindPoseIndices = this._cacheMesh._bindPoseIndices;
	            var pathMarks = this._cacheMesh._skinDataPathMarks;
	            for (var i = 0, n = this._cacheMesh.subMeshCount; i < n; i++) {
	                var subMeshBoneIndices = this._cacheMesh.getSubMesh(i)._boneIndicesList;
	                var subData = this._skinnedData[i];
	                for (var j = 0, m = subMeshBoneIndices.length; j < m; j++) {
	                    var boneIndices = subMeshBoneIndices[j];
	                    if (this._cacheAvatar && Laya.Render.supportWebGLPlusAnimation)
	                        this._computeSubSkinnedDataNative(this._cacheAnimator._animationNodeWorldMatrixs, this._cacheAnimationNodeIndices, this._cacheMesh._inverseBindPosesBuffer, boneIndices, meshBindPoseIndices, subData[j]);
	                    else
	                        this._computeSubSkinnedData(bindPoses, boneIndices, meshBindPoseIndices, subData[j], pathMarks);
	                }
	            }
	        }
	    }
	}
	SkinnedMeshRenderer._tempMatrix4x4 = new Matrix4x4();

	class SkinnedMeshSprite3D extends RenderableSprite3D {
	    constructor(mesh = null, name = null) {
	        super(name);
	        this._meshFilter = new MeshFilter(this);
	        this._render = new SkinnedMeshRenderer(this);
	        (mesh) && (this._meshFilter.sharedMesh = mesh);
	    }
	    static __init__() {
	        SkinnedMeshSprite3DShaderDeclaration.SHADERDEFINE_BONE = Shader3D.getDefineByName("BONE");
	    }
	    get meshFilter() {
	        return this._meshFilter;
	    }
	    get skinnedMeshRenderer() {
	        return this._render;
	    }
	    _parse(data, spriteMap) {
	        super._parse(data, spriteMap);
	        var render = this.skinnedMeshRenderer;
	        var lightmapIndex = data.lightmapIndex;
	        (lightmapIndex != null) && (render.lightmapIndex = lightmapIndex);
	        var lightmapScaleOffsetArray = data.lightmapScaleOffset;
	        (lightmapScaleOffsetArray) && (render.lightmapScaleOffset = new Vector4(lightmapScaleOffsetArray[0], lightmapScaleOffsetArray[1], lightmapScaleOffsetArray[2], lightmapScaleOffsetArray[3]));
	        var meshPath;
	        meshPath = data.meshPath;
	        if (meshPath) {
	            var mesh = Laya.Loader.getRes(meshPath);
	            (mesh) && (this.meshFilter.sharedMesh = mesh);
	        }
	        var materials = data.materials;
	        if (materials) {
	            var sharedMaterials = render.sharedMaterials;
	            var materialCount = materials.length;
	            sharedMaterials.length = materialCount;
	            for (var i = 0; i < materialCount; i++) {
	                sharedMaterials[i] = Laya.Loader.getRes(materials[i].path);
	            }
	            render.sharedMaterials = sharedMaterials;
	        }
	        var boundBox = data.boundBox;
	        var min = boundBox.min;
	        var max = boundBox.max;
	        render.localBounds.setMin(new Vector3(min[0], min[1], min[2]));
	        render.localBounds.setMax(new Vector3(max[0], max[1], max[2]));
	        if (spriteMap) {
	            var rootBoneData = data.rootBone;
	            render.rootBone = spriteMap[rootBoneData];
	            var bonesData = data.bones;
	            var n;
	            for (i = 0, n = bonesData.length; i < n; i++)
	                render.bones.push(spriteMap[bonesData[i]]);
	        }
	        else {
	            (data.rootBone) && (render._setRootBone(data.rootBone));
	        }
	    }
	    _changeHierarchyAnimator(animator) {
	        super._changeHierarchyAnimator(animator);
	        this.skinnedMeshRenderer._setCacheAnimator(animator);
	    }
	    _changeAnimatorAvatar(avatar) {
	        this.skinnedMeshRenderer._setCacheAvatar(avatar);
	    }
	    _cloneTo(destObject, srcRoot, dstRoot) {
	        var meshSprite3D = destObject;
	        meshSprite3D.meshFilter.sharedMesh = this.meshFilter.sharedMesh;
	        var meshRender = this._render;
	        var destMeshRender = meshSprite3D._render;
	        destMeshRender.enable = meshRender.enable;
	        destMeshRender.sharedMaterials = meshRender.sharedMaterials;
	        destMeshRender.castShadow = meshRender.castShadow;
	        var lightmapScaleOffset = meshRender.lightmapScaleOffset;
	        lightmapScaleOffset && (destMeshRender.lightmapScaleOffset = lightmapScaleOffset.clone());
	        destMeshRender.receiveShadow = meshRender.receiveShadow;
	        destMeshRender.sortingFudge = meshRender.sortingFudge;
	        destMeshRender._rootBone = meshRender._rootBone;
	        var bones = meshRender.bones;
	        var destBones = destMeshRender.bones;
	        var bonesCount = bones.length;
	        destBones.length = bonesCount;
	        var rootBone = meshRender.rootBone;
	        if (rootBone) {
	            var pathes = Utils3D._getHierarchyPath(srcRoot, rootBone, SkinnedMeshSprite3D._tempArray0);
	            if (pathes)
	                destMeshRender.rootBone = Utils3D._getNodeByHierarchyPath(dstRoot, pathes);
	            else
	                destMeshRender.rootBone = rootBone;
	        }
	        for (var i = 0; i < bones.length; i++) {
	            pathes = Utils3D._getHierarchyPath(srcRoot, bones[i], SkinnedMeshSprite3D._tempArray0);
	            if (pathes)
	                destBones[i] = Utils3D._getNodeByHierarchyPath(dstRoot, pathes);
	            else
	                destBones[i] = bones[i];
	        }
	        var lbb = meshRender.localBounds;
	        (lbb) && (lbb.cloneTo(destMeshRender.localBounds));
	        super._cloneTo(destObject, srcRoot, dstRoot);
	    }
	    destroy(destroyChild = true) {
	        if (this.destroyed)
	            return;
	        super.destroy(destroyChild);
	        this._meshFilter.destroy();
	    }
	    _create() {
	        return new SkinnedMeshSprite3D();
	    }
	}
	SkinnedMeshSprite3D._tempArray0 = [];
	SkinnedMeshSprite3D.BONES = Shader3D.propertyNameToID("u_Bones");

	class TrailMaterial extends BaseMaterial {
	    constructor() {
	        super();
	        this.setShaderName("Trail");
	        this._color = new Vector4(1.0, 1.0, 1.0, 1.0);
	        this._shaderValues.setVector(TrailMaterial.TINTCOLOR, new Vector4(1.0, 1.0, 1.0, 1.0));
	        this.renderMode = TrailMaterial.RENDERMODE_ALPHABLENDED;
	    }
	    static __initDefine__() {
	        TrailMaterial.SHADERDEFINE_MAINTEXTURE = Shader3D.getDefineByName("MAINTEXTURE");
	        TrailMaterial.SHADERDEFINE_TILINGOFFSET = Shader3D.getDefineByName("TILINGOFFSET");
	        TrailMaterial.SHADERDEFINE_ADDTIVEFOG = Shader3D.getDefineByName("ADDTIVEFOG");
	    }
	    get _TintColorR() {
	        return this._color.x;
	    }
	    set _TintColorR(value) {
	        this._color.x = value;
	        this.color = this._color;
	    }
	    get _TintColorG() {
	        return this._color.y;
	    }
	    set _TintColorG(value) {
	        this._color.y = value;
	        this.color = this._color;
	    }
	    get _TintColorB() {
	        return this._color.z;
	    }
	    set _TintColorB(value) {
	        this._color.z = value;
	        this.color = this._color;
	    }
	    get _TintColorA() {
	        return this._color.w;
	    }
	    set _TintColorA(value) {
	        this._color.w = value;
	        this.color = this._color;
	    }
	    get _MainTex_STX() {
	        return this._shaderValues.getVector(TrailMaterial.TILINGOFFSET).x;
	    }
	    set _MainTex_STX(x) {
	        var tilOff = this._shaderValues.getVector(TrailMaterial.TILINGOFFSET);
	        tilOff.x = x;
	        this.tilingOffset = tilOff;
	    }
	    get _MainTex_STY() {
	        return this._shaderValues.getVector(TrailMaterial.TILINGOFFSET).y;
	    }
	    set _MainTex_STY(y) {
	        var tilOff = this._shaderValues.getVector(TrailMaterial.TILINGOFFSET);
	        tilOff.y = y;
	        this.tilingOffset = tilOff;
	    }
	    get _MainTex_STZ() {
	        return this._shaderValues.getVector(TrailMaterial.TILINGOFFSET).z;
	    }
	    set _MainTex_STZ(z) {
	        var tilOff = this._shaderValues.getVector(TrailMaterial.TILINGOFFSET);
	        tilOff.z = z;
	        this.tilingOffset = tilOff;
	    }
	    get _MainTex_STW() {
	        return this._shaderValues.getVector(TrailMaterial.TILINGOFFSET).w;
	    }
	    set _MainTex_STW(w) {
	        var tilOff = this._shaderValues.getVector(TrailMaterial.TILINGOFFSET);
	        tilOff.w = w;
	        this.tilingOffset = tilOff;
	    }
	    set renderMode(value) {
	        switch (value) {
	            case TrailMaterial.RENDERMODE_ADDTIVE:
	                this.renderQueue = BaseMaterial.RENDERQUEUE_TRANSPARENT;
	                this.alphaTest = false;
	                this.depthWrite = false;
	                this.cull = RenderState.CULL_NONE;
	                this.blend = RenderState.BLEND_ENABLE_ALL;
	                this.blendSrc = RenderState.BLENDPARAM_SRC_ALPHA;
	                this.blendDst = RenderState.BLENDPARAM_ONE;
	                this.depthTest = RenderState.DEPTHTEST_LESS;
	                this._shaderValues.addDefine(TrailMaterial.SHADERDEFINE_ADDTIVEFOG);
	                break;
	            case TrailMaterial.RENDERMODE_ALPHABLENDED:
	                this.renderQueue = BaseMaterial.RENDERQUEUE_TRANSPARENT;
	                this.alphaTest = false;
	                this.depthWrite = false;
	                this.cull = RenderState.CULL_NONE;
	                this.blend = RenderState.BLEND_ENABLE_ALL;
	                this.blendSrc = RenderState.BLENDPARAM_SRC_ALPHA;
	                this.blendDst = RenderState.BLENDPARAM_ONE_MINUS_SRC_ALPHA;
	                this.depthTest = RenderState.DEPTHTEST_LESS;
	                this._shaderValues.removeDefine(TrailMaterial.SHADERDEFINE_ADDTIVEFOG);
	                break;
	            default:
	                throw new Error("TrailMaterial : renderMode value error.");
	        }
	    }
	    get colorR() {
	        return this._TintColorR;
	    }
	    set colorR(value) {
	        this._TintColorR = value;
	    }
	    get colorG() {
	        return this._TintColorG;
	    }
	    set colorG(value) {
	        this._TintColorG = value;
	    }
	    get colorB() {
	        return this._TintColorB;
	    }
	    set colorB(value) {
	        this._TintColorB = value;
	    }
	    get colorA() {
	        return this._TintColorA;
	    }
	    set colorA(value) {
	        this._TintColorA = value;
	    }
	    get color() {
	        return this._shaderValues.getVector(TrailMaterial.TINTCOLOR);
	    }
	    set color(value) {
	        this._shaderValues.setVector(TrailMaterial.TINTCOLOR, value);
	    }
	    get texture() {
	        return this._shaderValues.getTexture(TrailMaterial.MAINTEXTURE);
	    }
	    set texture(value) {
	        if (value)
	            this._shaderValues.addDefine(TrailMaterial.SHADERDEFINE_MAINTEXTURE);
	        else
	            this._shaderValues.removeDefine(TrailMaterial.SHADERDEFINE_MAINTEXTURE);
	        this._shaderValues.setTexture(TrailMaterial.MAINTEXTURE, value);
	    }
	    get tilingOffsetX() {
	        return this._MainTex_STX;
	    }
	    set tilingOffsetX(x) {
	        this._MainTex_STX = x;
	    }
	    get tilingOffsetY() {
	        return this._MainTex_STY;
	    }
	    set tilingOffsetY(y) {
	        this._MainTex_STY = y;
	    }
	    get tilingOffsetZ() {
	        return this._MainTex_STZ;
	    }
	    set tilingOffsetZ(z) {
	        this._MainTex_STZ = z;
	    }
	    get tilingOffsetW() {
	        return this._MainTex_STW;
	    }
	    set tilingOffsetW(w) {
	        this._MainTex_STW = w;
	    }
	    get tilingOffset() {
	        return this._shaderValues.getVector(TrailMaterial.TILINGOFFSET);
	    }
	    set tilingOffset(value) {
	        if (value) {
	            if (value.x != 1 || value.y != 1 || value.z != 0 || value.w != 0)
	                this._shaderValues.addDefine(TrailMaterial.SHADERDEFINE_TILINGOFFSET);
	            else
	                this._shaderValues.removeDefine(TrailMaterial.SHADERDEFINE_TILINGOFFSET);
	        }
	        else {
	            this._shaderValues.removeDefine(TrailMaterial.SHADERDEFINE_TILINGOFFSET);
	        }
	        this._shaderValues.setVector(TrailMaterial.TILINGOFFSET, value);
	    }
	    set depthWrite(value) {
	        this._shaderValues.setBool(TrailMaterial.DEPTH_WRITE, value);
	    }
	    get depthWrite() {
	        return this._shaderValues.getBool(TrailMaterial.DEPTH_WRITE);
	    }
	    set cull(value) {
	        this._shaderValues.setInt(TrailMaterial.CULL, value);
	    }
	    get cull() {
	        return this._shaderValues.getInt(TrailMaterial.CULL);
	    }
	    set blend(value) {
	        this._shaderValues.setInt(TrailMaterial.BLEND, value);
	    }
	    get blend() {
	        return this._shaderValues.getInt(TrailMaterial.BLEND);
	    }
	    set blendSrc(value) {
	        this._shaderValues.setInt(TrailMaterial.BLEND_SRC, value);
	    }
	    get blendSrc() {
	        return this._shaderValues.getInt(TrailMaterial.BLEND_SRC);
	    }
	    set blendDst(value) {
	        this._shaderValues.setInt(TrailMaterial.BLEND_DST, value);
	    }
	    get blendDst() {
	        return this._shaderValues.getInt(TrailMaterial.BLEND_DST);
	    }
	    set depthTest(value) {
	        this._shaderValues.setInt(TrailMaterial.DEPTH_TEST, value);
	    }
	    get depthTest() {
	        return this._shaderValues.getInt(TrailMaterial.DEPTH_TEST);
	    }
	    clone() {
	        var dest = new TrailMaterial();
	        this.cloneTo(dest);
	        return dest;
	    }
	}
	TrailMaterial.RENDERMODE_ALPHABLENDED = 0;
	TrailMaterial.RENDERMODE_ADDTIVE = 1;
	TrailMaterial.MAINTEXTURE = Shader3D.propertyNameToID("u_MainTexture");
	TrailMaterial.TINTCOLOR = Shader3D.propertyNameToID("u_MainColor");
	TrailMaterial.TILINGOFFSET = Shader3D.propertyNameToID("u_TilingOffset");
	TrailMaterial.CULL = Shader3D.propertyNameToID("s_Cull");
	TrailMaterial.BLEND = Shader3D.propertyNameToID("s_Blend");
	TrailMaterial.BLEND_SRC = Shader3D.propertyNameToID("s_BlendSrc");
	TrailMaterial.BLEND_DST = Shader3D.propertyNameToID("s_BlendDst");
	TrailMaterial.DEPTH_TEST = Shader3D.propertyNameToID("s_DepthTest");
	TrailMaterial.DEPTH_WRITE = Shader3D.propertyNameToID("s_DepthWrite");

	class TextureMode {
	}
	TextureMode.Stretch = 0;
	TextureMode.Tile = 1;

	(function (TrailAlignment) {
	    TrailAlignment[TrailAlignment["View"] = 0] = "View";
	    TrailAlignment[TrailAlignment["TransformZ"] = 1] = "TransformZ";
	})(exports.TrailAlignment || (exports.TrailAlignment = {}));

	class VertexTrail {
	    constructor() {
	    }
	    static get vertexDeclaration1() {
	        return VertexTrail._vertexDeclaration1;
	    }
	    static get vertexDeclaration2() {
	        return VertexTrail._vertexDeclaration2;
	    }
	    get vertexDeclaration() {
	        return VertexTrail._vertexDeclaration1;
	    }
	    static __init__() {
	        VertexTrail._vertexDeclaration1 = new VertexDeclaration(32, [new VertexElement(0, VertexElementFormat.Vector3, VertexTrail.TRAIL_POSITION0),
	            new VertexElement(12, VertexElementFormat.Vector3, VertexTrail.TRAIL_OFFSETVECTOR),
	            new VertexElement(24, VertexElementFormat.Single, VertexTrail.TRAIL_TIME0),
	            new VertexElement(28, VertexElementFormat.Single, VertexTrail.TRAIL_TEXTURECOORDINATE0Y)]);
	        VertexTrail._vertexDeclaration2 = new VertexDeclaration(20, [new VertexElement(0, VertexElementFormat.Single, VertexTrail.TRAIL_TEXTURECOORDINATE0X),
	            new VertexElement(4, VertexElementFormat.Color, VertexTrail.TRAIL_COLOR)]);
	    }
	}
	VertexTrail.TRAIL_POSITION0 = 0;
	VertexTrail.TRAIL_OFFSETVECTOR = 1;
	VertexTrail.TRAIL_TIME0 = 2;
	VertexTrail.TRAIL_TEXTURECOORDINATE0Y = 3;
	VertexTrail.TRAIL_TEXTURECOORDINATE0X = 4;
	VertexTrail.TRAIL_COLOR = 5;

	class TrailGeometry extends GeometryElement {
	    constructor(owner) {
	        super();
	        this._floatCountPerVertices1 = 8;
	        this._floatCountPerVertices2 = 5;
	        this._increaseSegementCount = 16;
	        this._activeIndex = 0;
	        this._endIndex = 0;
	        this._needAddFirstVertex = false;
	        this._isTempEndVertex = false;
	        this._vertices1 = null;
	        this._vertices2 = null;
	        this._lastFixedVertexPosition = new Vector3();
	        this._bufferState = new BufferState();
	        this.tmpColor = new Color();
	        this._disappearBoundsMode = false;
	        this._owner = owner;
	        this._segementCount = this._increaseSegementCount;
	        this._resizeData(this._segementCount, this._bufferState);
	        var bounds = this._owner._owner.trailRenderer.bounds;
	        var sprite3dPosition = this._owner._owner.transform.position;
	        bounds.setMin(sprite3dPosition);
	        bounds.setMax(sprite3dPosition);
	        Laya.Render.supportWebGLPlusCulling && this._calculateBoundingBoxForNative();
	    }
	    _resizeData(segementCount, bufferState) {
	        this._subBirthTime = new Float32Array(segementCount);
	        this._subDistance = new Float64Array(segementCount);
	        var gl = Laya.LayaGL.instance;
	        var vertexCount = segementCount * 2;
	        var vertexDeclaration1 = VertexTrail.vertexDeclaration1;
	        var vertexDeclaration2 = VertexTrail.vertexDeclaration2;
	        var vertexBuffers = [];
	        var vertexbuffer1Size = vertexCount * vertexDeclaration1.vertexStride;
	        var vertexbuffer2Size = vertexCount * vertexDeclaration2.vertexStride;
	        var memorySize = vertexbuffer1Size + vertexbuffer2Size;
	        this._vertices1 = new Float32Array(vertexCount * this._floatCountPerVertices1);
	        this._vertices2 = new Float32Array(vertexCount * this._floatCountPerVertices2);
	        this._vertexBuffer1 = new VertexBuffer3D(vertexbuffer1Size, gl.STATIC_DRAW, false);
	        this._vertexBuffer1.vertexDeclaration = vertexDeclaration1;
	        this._vertexBuffer2 = new VertexBuffer3D(vertexbuffer2Size, gl.DYNAMIC_DRAW, false);
	        this._vertexBuffer2.vertexDeclaration = vertexDeclaration2;
	        vertexBuffers.push(this._vertexBuffer1);
	        vertexBuffers.push(this._vertexBuffer2);
	        bufferState.bind();
	        bufferState.applyVertexBuffers(vertexBuffers);
	        bufferState.unBind();
	        Laya.Resource._addMemory(memorySize, memorySize);
	    }
	    _resetData() {
	        var count = this._endIndex - this._activeIndex;
	        var oldVertices1 = new Float32Array(this._vertices1.buffer, this._floatCountPerVertices1 * 2 * this._activeIndex * 4, this._floatCountPerVertices1 * 2 * count);
	        var oldVertices2 = new Float32Array(this._vertices2.buffer, this._floatCountPerVertices2 * 2 * this._activeIndex * 4, this._floatCountPerVertices2 * 2 * count);
	        var oldSubDistance = new Float64Array(this._subDistance.buffer, this._activeIndex * 8, count);
	        var oldSubBirthTime = new Float32Array(this._subBirthTime.buffer, this._activeIndex * 4, count);
	        if (count === this._segementCount) {
	            this._vertexBuffer1.destroy();
	            this._vertexBuffer2.destroy();
	            this._segementCount += this._increaseSegementCount;
	            this._resizeData(this._segementCount, this._bufferState);
	        }
	        this._vertices1.set(oldVertices1, 0);
	        this._vertices2.set(oldVertices2, 0);
	        this._subDistance.set(oldSubDistance, 0);
	        this._subBirthTime.set(oldSubBirthTime, 0);
	        this._endIndex = count;
	        this._activeIndex = 0;
	        this._vertexBuffer1.setData(this._vertices1.buffer, 0, this._floatCountPerVertices1 * 2 * this._activeIndex * 4, this._floatCountPerVertices1 * 2 * count * 4);
	        this._vertexBuffer2.setData(this._vertices2.buffer, 0, this._floatCountPerVertices2 * 2 * this._activeIndex * 4, this._floatCountPerVertices2 * 2 * count * 4);
	    }
	    _updateTrail(camera, lastPosition, position) {
	        if (!Vector3.equals(lastPosition, position)) {
	            if ((this._endIndex - this._activeIndex) === 0)
	                this._addTrailByFirstPosition(camera, position);
	            else
	                this._addTrailByNextPosition(camera, position);
	        }
	    }
	    _addTrailByFirstPosition(camera, position) {
	        (this._endIndex === this._segementCount) && (this._resetData());
	        this._subDistance[this._endIndex] = 0;
	        this._subBirthTime[this._endIndex] = this._owner._curtime;
	        this._endIndex++;
	        position.cloneTo(this._lastFixedVertexPosition);
	        this._needAddFirstVertex = true;
	    }
	    _addTrailByNextPosition(camera, position) {
	        var delVector3 = TrailGeometry._tempVector30;
	        var pointAtoBVector3 = TrailGeometry._tempVector31;
	        switch (this._owner.alignment) {
	            case exports.TrailAlignment.View:
	                var cameraMatrix = camera.viewMatrix;
	                Vector3.transformCoordinate(position, cameraMatrix, TrailGeometry._tempVector33);
	                Vector3.transformCoordinate(this._lastFixedVertexPosition, cameraMatrix, TrailGeometry._tempVector34);
	                Vector3.subtract(TrailGeometry._tempVector33, TrailGeometry._tempVector34, delVector3);
	                Vector3.cross(TrailGeometry._tempVector33, delVector3, pointAtoBVector3);
	                break;
	            case exports.TrailAlignment.TransformZ:
	                Vector3.subtract(position, this._lastFixedVertexPosition, delVector3);
	                var forward = TrailGeometry._tempVector32;
	                this._owner._owner.transform.localMatrix.getForward(forward);
	                Vector3.cross(delVector3, forward, pointAtoBVector3);
	                break;
	        }
	        Vector3.normalize(pointAtoBVector3, pointAtoBVector3);
	        Vector3.scale(pointAtoBVector3, this._owner.widthMultiplier / 2, pointAtoBVector3);
	        var delLength = Vector3.scalarLength(delVector3);
	        var tempEndIndex;
	        var offset;
	        if (this._needAddFirstVertex) {
	            this._updateVerticesByPositionData(position, pointAtoBVector3, this._endIndex - 1);
	            this._needAddFirstVertex = false;
	        }
	        if (delLength - this._owner.minVertexDistance >= MathUtils3D.zeroTolerance) {
	            if (this._isTempEndVertex) {
	                tempEndIndex = this._endIndex - 1;
	                offset = delLength - this._subDistance[tempEndIndex];
	                this._updateVerticesByPosition(position, pointAtoBVector3, delLength, tempEndIndex);
	                this._owner._totalLength += offset;
	            }
	            else {
	                (this._endIndex === this._segementCount) && (this._resetData());
	                this._updateVerticesByPosition(position, pointAtoBVector3, delLength, this._endIndex);
	                this._owner._totalLength += delLength;
	                this._endIndex++;
	            }
	            position.cloneTo(this._lastFixedVertexPosition);
	            this._isTempEndVertex = false;
	        }
	        else {
	            if (this._isTempEndVertex) {
	                tempEndIndex = this._endIndex - 1;
	                offset = delLength - this._subDistance[tempEndIndex];
	                this._updateVerticesByPosition(position, pointAtoBVector3, delLength, tempEndIndex);
	                this._owner._totalLength += offset;
	            }
	            else {
	                (this._endIndex === this._segementCount) && (this._resetData());
	                this._updateVerticesByPosition(position, pointAtoBVector3, delLength, this._endIndex);
	                this._owner._totalLength += delLength;
	                this._endIndex++;
	            }
	            this._isTempEndVertex = true;
	        }
	    }
	    _updateVerticesByPositionData(position, pointAtoBVector3, index) {
	        var vertexOffset = this._floatCountPerVertices1 * 2 * index;
	        var curtime = this._owner._curtime;
	        this._vertices1[vertexOffset] = position.x;
	        this._vertices1[vertexOffset + 1] = position.y;
	        this._vertices1[vertexOffset + 2] = position.z;
	        this._vertices1[vertexOffset + 3] = -pointAtoBVector3.x;
	        this._vertices1[vertexOffset + 4] = -pointAtoBVector3.y;
	        this._vertices1[vertexOffset + 5] = -pointAtoBVector3.z;
	        this._vertices1[vertexOffset + 6] = curtime;
	        this._vertices1[vertexOffset + 7] = 1.0;
	        this._vertices1[vertexOffset + 8] = position.x;
	        this._vertices1[vertexOffset + 9] = position.y;
	        this._vertices1[vertexOffset + 10] = position.z;
	        this._vertices1[vertexOffset + 11] = pointAtoBVector3.x;
	        this._vertices1[vertexOffset + 12] = pointAtoBVector3.y;
	        this._vertices1[vertexOffset + 13] = pointAtoBVector3.z;
	        this._vertices1[vertexOffset + 14] = curtime;
	        this._vertices1[vertexOffset + 15] = 0.0;
	        var bounds = this._owner._owner.trailRenderer.bounds;
	        var min = bounds.getMin();
	        var max = bounds.getMax();
	        var up = TrailGeometry._tempVector35;
	        var down = TrailGeometry._tempVector36;
	        var out = TrailGeometry._tempVector32;
	        Vector3.add(position, pointAtoBVector3, up);
	        Vector3.subtract(position, pointAtoBVector3, down);
	        Vector3.min(down, up, out);
	        Vector3.min(min, out, min);
	        bounds.setMin(min);
	        Vector3.max(up, down, out);
	        Vector3.max(max, out, max);
	        bounds.setMax(max);
	        Laya.Render.supportWebGLPlusCulling && this._calculateBoundingBoxForNative();
	        var floatCount = this._floatCountPerVertices1 * 2;
	        this._vertexBuffer1.setData(this._vertices1.buffer, vertexOffset * 4, vertexOffset * 4, floatCount * 4);
	    }
	    _updateVerticesByPosition(position, pointAtoBVector3, delDistance, index) {
	        this._updateVerticesByPositionData(position, pointAtoBVector3, index);
	        this._subDistance[index] = delDistance;
	        this._subBirthTime[index] = this._owner._curtime;
	    }
	    _updateVertexBufferUV() {
	        var bounds;
	        var min, max;
	        if (this._disappearBoundsMode) {
	            bounds = this._owner._owner.trailRenderer.bounds;
	            min = bounds.getMin();
	            max = bounds.getMax();
	            min.setValue(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
	            max.setValue(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
	            Laya.Render.supportWebGLPlusCulling && this._calculateBoundingBoxForNative();
	        }
	        var vertexCount = this._endIndex;
	        var curLength = 0;
	        var gradient = this._owner.colorGradient;
	        var startAlphaIndex = gradient.colorAlphaKeysCount - 1;
	        var startColorIndex = gradient.colorRGBKeysCount - 1;
	        var totalLength = this._owner._totalLength;
	        var stride = this._floatCountPerVertices2 * 2;
	        for (var i = this._activeIndex; i < vertexCount; i++) {
	            (i !== this._activeIndex) && (curLength += this._subDistance[i]);
	            var uvX;
	            var lerpFactor;
	            if (this._owner.textureMode == TextureMode.Stretch) {
	                uvX = 1.0 - curLength / totalLength;
	                lerpFactor = uvX;
	            }
	            else {
	                lerpFactor = 1.0 - curLength / totalLength;
	                uvX = 1.0 - (totalLength - curLength);
	            }
	            startColorIndex = gradient.evaluateColorRGB(lerpFactor, this.tmpColor, startColorIndex, true);
	            startAlphaIndex = gradient.evaluateColorAlpha(lerpFactor, this.tmpColor, startAlphaIndex, true);
	            var index = i * stride;
	            this._vertices2[index + 0] = uvX;
	            this._vertices2[index + 1] = this.tmpColor.r;
	            this._vertices2[index + 2] = this.tmpColor.g;
	            this._vertices2[index + 3] = this.tmpColor.b;
	            this._vertices2[index + 4] = this.tmpColor.a;
	            this._vertices2[index + 5] = uvX;
	            this._vertices2[index + 6] = this.tmpColor.r;
	            this._vertices2[index + 7] = this.tmpColor.g;
	            this._vertices2[index + 8] = this.tmpColor.b;
	            this._vertices2[index + 9] = this.tmpColor.a;
	            if (this._disappearBoundsMode) {
	                var posOffset = this._floatCountPerVertices1 * 2 * i;
	                var pos = TrailGeometry._tempVector32;
	                var up = TrailGeometry._tempVector33;
	                var side = TrailGeometry._tempVector34;
	                pos.setValue(this._vertices1[posOffset + 0], this._vertices1[posOffset + 1], this._vertices1[posOffset + 2]);
	                up.setValue(this._vertices1[posOffset + 3], this._vertices1[posOffset + 4], this._vertices1[posOffset + 5]);
	                Vector3.add(pos, up, side);
	                Vector3.min(side, min, min);
	                Vector3.max(side, max, max);
	                Vector3.subtract(pos, up, side);
	                Vector3.min(side, min, min);
	                Vector3.max(side, max, max);
	            }
	        }
	        if (this._disappearBoundsMode) {
	            bounds.setMin(min);
	            bounds.setMax(max);
	            this._disappearBoundsMode = false;
	            Laya.Render.supportWebGLPlusCulling && this._calculateBoundingBoxForNative();
	        }
	        var offset = this._activeIndex * stride;
	        this._vertexBuffer2.setData(this._vertices2.buffer, offset * 4, offset * 4, (vertexCount * stride - offset) * 4);
	    }
	    _updateDisappear() {
	        var count = this._endIndex;
	        for (var i = this._activeIndex; i < count; i++) {
	            if (this._owner._curtime - this._subBirthTime[i] >= this._owner.time + MathUtils3D.zeroTolerance) {
	                var nextIndex = i + 1;
	                if (nextIndex !== count)
	                    this._owner._totalLength -= this._subDistance[nextIndex];
	                if (this._isTempEndVertex && (nextIndex === count - 1)) {
	                    var offset = this._floatCountPerVertices1 * i * 2;
	                    var fixedPos = this._lastFixedVertexPosition;
	                    fixedPos.x = this._vertices1[0];
	                    fixedPos.y = this._vertices1[1];
	                    fixedPos.z = this._vertices1[2];
	                    this._isTempEndVertex = false;
	                }
	                this._activeIndex++;
	                this._disappearBoundsMode = true;
	            }
	            else {
	                break;
	            }
	        }
	    }
	    _getType() {
	        return TrailGeometry._type;
	    }
	    _prepareRender(state) {
	        return this._endIndex - this._activeIndex > 1;
	    }
	    _render(state) {
	        this._bufferState.bind();
	        var gl = Laya.LayaGL.instance;
	        var start = this._activeIndex * 2;
	        var count = this._endIndex * 2 - start;
	        gl.drawArrays(gl.TRIANGLE_STRIP, start, count);
	        Laya.Stat.renderBatches++;
	        Laya.Stat.trianglesFaces += count - 2;
	    }
	    destroy() {
	        super.destroy();
	        var memorySize = this._vertexBuffer1._byteLength + this._vertexBuffer2._byteLength;
	        Laya.Resource._addMemory(-memorySize, -memorySize);
	        this._bufferState.destroy();
	        this._vertexBuffer1.destroy();
	        this._vertexBuffer2.destroy();
	        this._bufferState = null;
	        this._vertices1 = null;
	        this._vertexBuffer1 = null;
	        this._vertices2 = null;
	        this._vertexBuffer2 = null;
	        this._subBirthTime = null;
	        this._subDistance = null;
	        this._lastFixedVertexPosition = null;
	        this._disappearBoundsMode = false;
	    }
	    _calculateBoundingBoxForNative() {
	        var trail = this._owner._owner.trailRenderer;
	        var bounds = trail.bounds;
	        var min = bounds.getMin();
	        var max = bounds.getMax();
	        var buffer = FrustumCulling._cullingBuffer;
	        buffer[trail._cullingBufferIndex + 1] = min.x;
	        buffer[trail._cullingBufferIndex + 2] = min.y;
	        buffer[trail._cullingBufferIndex + 3] = min.z;
	        buffer[trail._cullingBufferIndex + 4] = max.x;
	        buffer[trail._cullingBufferIndex + 5] = max.y;
	        buffer[trail._cullingBufferIndex + 6] = max.z;
	    }
	}
	TrailGeometry.ALIGNMENT_VIEW = 0;
	TrailGeometry.ALIGNMENT_TRANSFORM_Z = 1;
	TrailGeometry._tempVector30 = new Vector3();
	TrailGeometry._tempVector31 = new Vector3();
	TrailGeometry._tempVector32 = new Vector3();
	TrailGeometry._tempVector33 = new Vector3();
	TrailGeometry._tempVector34 = new Vector3();
	TrailGeometry._tempVector35 = new Vector3();
	TrailGeometry._tempVector36 = new Vector3();
	TrailGeometry._type = GeometryElement._typeCounter++;

	class TrailFilter {
	    constructor(owner) {
	        this._totalLength = 0;
	        this._lastPosition = new Vector3();
	        this._curtime = 0;
	        this.alignment = TrailFilter.ALIGNMENT_VIEW;
	        this._owner = owner;
	        this._initDefaultData();
	        this.addRenderElement();
	    }
	    get time() {
	        return this._time;
	    }
	    set time(value) {
	        this._time = value;
	        this._owner._render._shaderValues.setNumber(TrailFilter.LIFETIME, value);
	    }
	    get minVertexDistance() {
	        return this._minVertexDistance;
	    }
	    set minVertexDistance(value) {
	        this._minVertexDistance = value;
	    }
	    get widthMultiplier() {
	        return this._widthMultiplier;
	    }
	    set widthMultiplier(value) {
	        this._widthMultiplier = value;
	    }
	    get widthCurve() {
	        return this._widthCurve;
	    }
	    set widthCurve(value) {
	        this._widthCurve = value;
	        var widthCurveFloatArray = new Float32Array(value.length * 4);
	        var i, j, index = 0;
	        for (i = 0, j = value.length; i < j; i++) {
	            widthCurveFloatArray[index++] = value[i].time;
	            widthCurveFloatArray[index++] = value[i].inTangent;
	            widthCurveFloatArray[index++] = value[i].outTangent;
	            widthCurveFloatArray[index++] = value[i].value;
	        }
	        this._owner._render._shaderValues.setBuffer(TrailFilter.WIDTHCURVE, widthCurveFloatArray);
	        this._owner._render._shaderValues.setInt(TrailFilter.WIDTHCURVEKEYLENGTH, value.length);
	    }
	    get colorGradient() {
	        return this._colorGradient;
	    }
	    set colorGradient(value) {
	        this._colorGradient = value;
	    }
	    get textureMode() {
	        return this._textureMode;
	    }
	    set textureMode(value) {
	        this._textureMode = value;
	    }
	    addRenderElement() {
	        var render = this._owner._render;
	        var elements = render._renderElements;
	        var material = render.sharedMaterials[0];
	        (material) || (material = TrailMaterial.defaultMaterial);
	        var element = new RenderElement();
	        element.setTransform(this._owner._transform);
	        element.render = render;
	        element.material = material;
	        this._trialGeometry = new TrailGeometry(this);
	        element.setGeometry(this._trialGeometry);
	        elements.push(element);
	    }
	    _update(state) {
	        var render = this._owner._render;
	        this._curtime += state.scene.timer._delta / 1000;
	        render._shaderValues.setNumber(TrailFilter.CURTIME, this._curtime);
	        var curPos = this._owner.transform.position;
	        var element = render._renderElements[0]._geometry;
	        element._updateDisappear();
	        element._updateTrail(state.camera, this._lastPosition, curPos);
	        element._updateVertexBufferUV();
	        curPos.cloneTo(this._lastPosition);
	    }
	    _initDefaultData() {
	        this.time = 5.0;
	        this.minVertexDistance = 0.1;
	        this.widthMultiplier = 1;
	        this.textureMode = TextureMode.Stretch;
	        var widthKeyFrames = [];
	        var widthKeyFrame1 = new FloatKeyframe();
	        widthKeyFrame1.time = 0;
	        widthKeyFrame1.inTangent = 0;
	        widthKeyFrame1.outTangent = 0;
	        widthKeyFrame1.value = 1;
	        widthKeyFrames.push(widthKeyFrame1);
	        var widthKeyFrame2 = new FloatKeyframe();
	        widthKeyFrame2.time = 1;
	        widthKeyFrame2.inTangent = 0;
	        widthKeyFrame2.outTangent = 0;
	        widthKeyFrame2.value = 1;
	        widthKeyFrames.push(widthKeyFrame2);
	        this.widthCurve = widthKeyFrames;
	        var gradient = new Gradient(2, 2);
	        gradient.mode = GradientMode.Blend;
	        gradient.addColorRGB(0, Color.WHITE);
	        gradient.addColorRGB(1, Color.WHITE);
	        gradient.addColorAlpha(0, 1);
	        gradient.addColorAlpha(1, 1);
	        this.colorGradient = gradient;
	    }
	    destroy() {
	        this._trialGeometry.destroy();
	        this._trialGeometry = null;
	        this._widthCurve = null;
	        this._colorGradient = null;
	    }
	}
	TrailFilter.CURTIME = Shader3D.propertyNameToID("u_CurTime");
	TrailFilter.LIFETIME = Shader3D.propertyNameToID("u_LifeTime");
	TrailFilter.WIDTHCURVE = Shader3D.propertyNameToID("u_WidthCurve");
	TrailFilter.WIDTHCURVEKEYLENGTH = Shader3D.propertyNameToID("u_WidthCurveKeyLength");
	TrailFilter.ALIGNMENT_VIEW = 0;
	TrailFilter.ALIGNMENT_TRANSFORM_Z = 1;

	class TrailRenderer extends BaseRender {
	    constructor(owner) {
	        super(owner);
	        this._projectionViewWorldMatrix = new Matrix4x4();
	    }
	    _calculateBoundingBox() {
	    }
	    _needRender(boundFrustum, context) {
	        this._owner.trailFilter._update(context);
	        if (boundFrustum)
	            return boundFrustum.intersects(this.bounds._getBoundBox());
	        else
	            return true;
	    }
	    _updateForNative(context) {
	        this._owner.trailFilter._update(context);
	    }
	    _renderUpdate(state, transform) {
	        super._renderUpdate(state, transform);
	    }
	    _renderUpdateWithCamera(context, transform) {
	        var projectionView = context.projectionViewMatrix;
	        if (transform) {
	            Matrix4x4.multiply(projectionView, transform.worldMatrix, this._projectionViewWorldMatrix);
	            this._shaderValues.setMatrix4x4(Sprite3D.MVPMATRIX, this._projectionViewWorldMatrix);
	        }
	        else {
	            this._shaderValues.setMatrix4x4(Sprite3D.MVPMATRIX, projectionView);
	        }
	    }
	}

	class TrailSprite3D extends RenderableSprite3D {
	    static __init__() {
	    }
	    get trailFilter() {
	        return this._geometryFilter;
	    }
	    get trailRenderer() {
	        return this._render;
	    }
	    constructor(name = null) {
	        super(name);
	        this._render = new TrailRenderer(this);
	        this._geometryFilter = new TrailFilter(this);
	    }
	    _parse(data, spriteMap) {
	        super._parse(data, spriteMap);
	        var render = this._render;
	        var filter = this._geometryFilter;
	        var i, j;
	        var materials = data.materials;
	        if (materials) {
	            var sharedMaterials = render.sharedMaterials;
	            var materialCount = materials.length;
	            sharedMaterials.length = materialCount;
	            for (i = 0; i < materialCount; i++)
	                sharedMaterials[i] = Laya.Loader.getRes(materials[i].path);
	            render.sharedMaterials = sharedMaterials;
	        }
	        filter.time = data.time;
	        filter.minVertexDistance = data.minVertexDistance;
	        filter.widthMultiplier = data.widthMultiplier;
	        filter.textureMode = data.textureMode;
	        (data.alignment != null) && (filter.alignment = data.alignment);
	        var widthCurve = [];
	        var widthCurveData = data.widthCurve;
	        for (i = 0, j = widthCurveData.length; i < j; i++) {
	            var trailkeyframe = new FloatKeyframe();
	            trailkeyframe.time = widthCurveData[i].time;
	            trailkeyframe.inTangent = widthCurveData[i].inTangent;
	            trailkeyframe.outTangent = widthCurveData[i].outTangent;
	            trailkeyframe.value = widthCurveData[i].value;
	            widthCurve.push(trailkeyframe);
	        }
	        filter.widthCurve = widthCurve;
	        var colorGradientData = data.colorGradient;
	        var colorKeys = colorGradientData.colorKeys;
	        var alphaKeys = colorGradientData.alphaKeys;
	        var colorGradient = new Gradient(colorKeys.length, alphaKeys.length);
	        colorGradient.mode = colorGradientData.mode;
	        for (i = 0, j = colorKeys.length; i < j; i++) {
	            var colorKey = colorKeys[i];
	            colorGradient.addColorRGB(colorKey.time, new Color(colorKey.value[0], colorKey.value[1], colorKey.value[2], 1.0));
	        }
	        for (i = 0, j = alphaKeys.length; i < j; i++) {
	            var alphaKey = alphaKeys[i];
	            colorGradient.addColorAlpha(alphaKey.time, alphaKey.value);
	        }
	        filter.colorGradient = colorGradient;
	    }
	    _onActive() {
	        super._onActive();
	        this._transform.position.cloneTo(this._geometryFilter._lastPosition);
	    }
	    _cloneTo(destObject, srcSprite, dstSprite) {
	        super._cloneTo(destObject, srcSprite, dstSprite);
	        var i, j;
	        var destTrailSprite3D = destObject;
	        var destTrailFilter = destTrailSprite3D.trailFilter;
	        destTrailFilter.time = this.trailFilter.time;
	        destTrailFilter.minVertexDistance = this.trailFilter.minVertexDistance;
	        destTrailFilter.widthMultiplier = this.trailFilter.widthMultiplier;
	        destTrailFilter.textureMode = this.trailFilter.textureMode;
	        destTrailFilter.alignment = this.trailFilter.alignment;
	        var widthCurveData = this.trailFilter.widthCurve;
	        var widthCurve = [];
	        for (i = 0, j = widthCurveData.length; i < j; i++) {
	            var keyFrame = new FloatKeyframe();
	            widthCurveData[i].cloneTo(keyFrame);
	            widthCurve.push(keyFrame);
	        }
	        destTrailFilter.widthCurve = widthCurve;
	        var destColorGradient = new Gradient(this.trailFilter.colorGradient.maxColorRGBKeysCount, this.trailFilter.colorGradient.maxColorAlphaKeysCount);
	        this.trailFilter.colorGradient.cloneTo(destColorGradient);
	        destTrailFilter.colorGradient = destColorGradient;
	        var destTrailRender = destTrailSprite3D.trailRenderer;
	        destTrailRender.sharedMaterial = this.trailRenderer.sharedMaterial;
	    }
	    destroy(destroyChild = true) {
	        if (this.destroyed)
	            return;
	        super.destroy(destroyChild);
	        this._geometryFilter.destroy();
	        this._geometryFilter = null;
	    }
	    _create() {
	        return new TrailSprite3D();
	    }
	}

	class VertexPositionTerrain {
	    constructor(position, normal, textureCoord0, textureCoord1) {
	        this._position = position;
	        this._normal = normal;
	        this._textureCoord0 = textureCoord0;
	        this._textureCoord1 = textureCoord1;
	    }
	    static __init__() {
	        VertexPositionTerrain._vertexDeclaration = new VertexDeclaration(40, [new VertexElement(0, VertexElementFormat.Vector3, VertexPositionTerrain.TERRAIN_POSITION0),
	            new VertexElement(12, VertexElementFormat.Vector3, VertexPositionTerrain.TERRAIN_NORMAL0),
	            new VertexElement(24, VertexElementFormat.Vector2, VertexPositionTerrain.TERRAIN_TEXTURECOORDINATE0),
	            new VertexElement(32, VertexElementFormat.Vector2, VertexPositionTerrain.TERRAIN_TEXTURECOORDINATE1)]);
	    }
	    static get vertexDeclaration() {
	        return VertexPositionTerrain._vertexDeclaration;
	    }
	    get position() {
	        return this._position;
	    }
	    get normal() {
	        return this._normal;
	    }
	    get textureCoord0() {
	        return this._textureCoord0;
	    }
	    get textureCoord1() {
	        return this._textureCoord1;
	    }
	    get vertexDeclaration() {
	        return VertexPositionTerrain._vertexDeclaration;
	    }
	}
	VertexPositionTerrain.TERRAIN_POSITION0 = 0;
	VertexPositionTerrain.TERRAIN_NORMAL0 = 1;
	VertexPositionTerrain.TERRAIN_TEXTURECOORDINATE0 = 2;
	VertexPositionTerrain.TERRAIN_TEXTURECOORDINATE1 = 3;

	class CharacterController extends PhysicsComponent {
	    constructor(stepheight = 0.1, upAxis = null, collisionGroup = Physics3DUtils.COLLISIONFILTERGROUP_DEFAULTFILTER, canCollideWith = Physics3DUtils.COLLISIONFILTERGROUP_ALLFILTER) {
	        super(collisionGroup, canCollideWith);
	        this._upAxis = new Vector3(0, 1, 0);
	        this._maxSlope = 45.0;
	        this._jumpSpeed = 10.0;
	        this._fallSpeed = 55.0;
	        this._gravity = new Vector3(0, -9.8 * 3, 0);
	        this._nativeKinematicCharacter = null;
	        this._stepHeight = stepheight;
	        (upAxis) && (this._upAxis = upAxis);
	    }
	    static __init__() {
	        CharacterController._nativeTempVector30 = new Physics3D._physics3D.btVector3(0, 0, 0);
	    }
	    get fallSpeed() {
	        return this._fallSpeed;
	    }
	    set fallSpeed(value) {
	        this._fallSpeed = value;
	        this._nativeKinematicCharacter.setFallSpeed(value);
	    }
	    get jumpSpeed() {
	        return this._jumpSpeed;
	    }
	    set jumpSpeed(value) {
	        this._jumpSpeed = value;
	        this._nativeKinematicCharacter.setJumpSpeed(value);
	    }
	    get gravity() {
	        return this._gravity;
	    }
	    set gravity(value) {
	        this._gravity = value;
	        var nativeGravity = CharacterController._nativeTempVector30;
	        nativeGravity.setValue(-value.x, value.y, value.z);
	        this._nativeKinematicCharacter.setGravity(nativeGravity);
	    }
	    get maxSlope() {
	        return this._maxSlope;
	    }
	    set maxSlope(value) {
	        this._maxSlope = value;
	        this._nativeKinematicCharacter.setMaxSlope((value / 180) * Math.PI);
	    }
	    get isGrounded() {
	        return this._nativeKinematicCharacter.onGround();
	    }
	    get stepHeight() {
	        return this._stepHeight;
	    }
	    set stepHeight(value) {
	        this._stepHeight = value;
	        this._constructCharacter();
	    }
	    get upAxis() {
	        return this._upAxis;
	    }
	    set upAxis(value) {
	        this._upAxis = value;
	        this._constructCharacter();
	    }
	    _constructCharacter() {
	        var physics3D = Physics3D._physics3D;
	        if (this._nativeKinematicCharacter)
	            physics3D.destroy(this._nativeKinematicCharacter);
	        var nativeUpAxis = CharacterController._nativeTempVector30;
	        nativeUpAxis.setValue(this._upAxis.x, this._upAxis.y, this._upAxis.z);
	        this._nativeKinematicCharacter = new physics3D.btKinematicCharacterController(this._nativeColliderObject, this._colliderShape._nativeShape, this._stepHeight, nativeUpAxis);
	        this.fallSpeed = this._fallSpeed;
	        this.maxSlope = this._maxSlope;
	        this.jumpSpeed = this._jumpSpeed;
	        this.gravity = this._gravity;
	    }
	    _onShapeChange(colShape) {
	        super._onShapeChange(colShape);
	        this._constructCharacter();
	    }
	    _onAdded() {
	        var physics3D = Physics3D._physics3D;
	        var ghostObject = new physics3D.btPairCachingGhostObject();
	        ghostObject.setUserIndex(this.id);
	        ghostObject.setCollisionFlags(PhysicsComponent.COLLISIONFLAGS_CHARACTER_OBJECT);
	        this._nativeColliderObject = ghostObject;
	        if (this._colliderShape)
	            this._constructCharacter();
	        super._onAdded();
	    }
	    _addToSimulation() {
	        this._simulation._characters.push(this);
	        this._simulation._addCharacter(this, this._collisionGroup, this._canCollideWith);
	    }
	    _removeFromSimulation() {
	        this._simulation._removeCharacter(this);
	        var characters = this._simulation._characters;
	        characters.splice(characters.indexOf(this), 1);
	    }
	    _cloneTo(dest) {
	        super._cloneTo(dest);
	        var destCharacterController = dest;
	        destCharacterController.stepHeight = this._stepHeight;
	        destCharacterController.upAxis = this._upAxis;
	        destCharacterController.maxSlope = this._maxSlope;
	        destCharacterController.jumpSpeed = this._jumpSpeed;
	        destCharacterController.fallSpeed = this._fallSpeed;
	        destCharacterController.gravity = this._gravity;
	    }
	    _onDestroy() {
	        Physics3D._physics3D.destroy(this._nativeKinematicCharacter);
	        super._onDestroy();
	        this._nativeKinematicCharacter = null;
	    }
	    move(movement) {
	        var nativeMovement = CharacterController._nativeVector30;
	        nativeMovement.setValue(-movement.x, movement.y, movement.z);
	        this._nativeKinematicCharacter.setWalkDirection(nativeMovement);
	    }
	    jump(velocity = null) {
	        if (velocity) {
	            var nativeVelocity = CharacterController._nativeVector30;
	            Utils3D._convertToBulletVec3(velocity, nativeVelocity, true);
	            this._nativeKinematicCharacter.jump(nativeVelocity);
	        }
	        else {
	            this._nativeKinematicCharacter.jump();
	        }
	    }
	}
	CharacterController.UPAXIS_X = 0;
	CharacterController.UPAXIS_Y = 1;
	CharacterController.UPAXIS_Z = 2;

	class PhysicsTriggerComponent extends PhysicsComponent {
	    constructor(collisionGroup, canCollideWith) {
	        super(collisionGroup, canCollideWith);
	        this._isTrigger = false;
	    }
	    get isTrigger() {
	        return this._isTrigger;
	    }
	    set isTrigger(value) {
	        this._isTrigger = value;
	        if (this._nativeColliderObject) {
	            var flags = this._nativeColliderObject.getCollisionFlags();
	            if (value) {
	                if ((flags & PhysicsComponent.COLLISIONFLAGS_NO_CONTACT_RESPONSE) === 0)
	                    this._nativeColliderObject.setCollisionFlags(flags | PhysicsComponent.COLLISIONFLAGS_NO_CONTACT_RESPONSE);
	            }
	            else {
	                if ((flags & PhysicsComponent.COLLISIONFLAGS_NO_CONTACT_RESPONSE) !== 0)
	                    this._nativeColliderObject.setCollisionFlags(flags ^ PhysicsComponent.COLLISIONFLAGS_NO_CONTACT_RESPONSE);
	            }
	        }
	    }
	    _onAdded() {
	        super._onAdded();
	        this.isTrigger = this._isTrigger;
	    }
	    _cloneTo(dest) {
	        super._cloneTo(dest);
	        dest.isTrigger = this._isTrigger;
	    }
	}

	class PhysicsCollider extends PhysicsTriggerComponent {
	    constructor(collisionGroup = Physics3DUtils.COLLISIONFILTERGROUP_DEFAULTFILTER, canCollideWith = Physics3DUtils.COLLISIONFILTERGROUP_ALLFILTER) {
	        super(collisionGroup, canCollideWith);
	        this._enableProcessCollisions = false;
	    }
	    _addToSimulation() {
	        this._simulation._addPhysicsCollider(this, this._collisionGroup, this._canCollideWith);
	    }
	    _removeFromSimulation() {
	        this._simulation._removePhysicsCollider(this);
	    }
	    _onTransformChanged(flag) {
	        flag &= Transform3D.TRANSFORM_WORLDPOSITION | Transform3D.TRANSFORM_WORLDQUATERNION | Transform3D.TRANSFORM_WORLDSCALE;
	        if (flag) {
	            this._transformFlag |= flag;
	            if (this._isValid() && this._inPhysicUpdateListIndex === -1)
	                this._simulation._physicsUpdateList.add(this);
	        }
	    }
	    _parse(data) {
	        (data.friction != null) && (this.friction = data.friction);
	        (data.rollingFriction != null) && (this.rollingFriction = data.rollingFriction);
	        (data.restitution != null) && (this.restitution = data.restitution);
	        (data.isTrigger != null) && (this.isTrigger = data.isTrigger);
	        super._parse(data);
	        this._parseShape(data.shapes);
	    }
	    _onAdded() {
	        var physics3D = Physics3D._physics3D;
	        var btColObj = new physics3D.btCollisionObject();
	        btColObj.setUserIndex(this.id);
	        btColObj.forceActivationState(PhysicsComponent.ACTIVATIONSTATE_DISABLE_SIMULATION);
	        var flags = btColObj.getCollisionFlags();
	        if (this.owner.isStatic) {
	            if ((flags & PhysicsComponent.COLLISIONFLAGS_KINEMATIC_OBJECT) > 0)
	                flags = flags ^ PhysicsComponent.COLLISIONFLAGS_KINEMATIC_OBJECT;
	            flags = flags | PhysicsComponent.COLLISIONFLAGS_STATIC_OBJECT;
	        }
	        else {
	            if ((flags & PhysicsComponent.COLLISIONFLAGS_STATIC_OBJECT) > 0)
	                flags = flags ^ PhysicsComponent.COLLISIONFLAGS_STATIC_OBJECT;
	            flags = flags | PhysicsComponent.COLLISIONFLAGS_KINEMATIC_OBJECT;
	        }
	        btColObj.setCollisionFlags(flags);
	        this._nativeColliderObject = btColObj;
	        super._onAdded();
	    }
	}

	class Rigidbody3D extends PhysicsTriggerComponent {
	    constructor(collisionGroup = Physics3DUtils.COLLISIONFILTERGROUP_DEFAULTFILTER, canCollideWith = Physics3DUtils.COLLISIONFILTERGROUP_ALLFILTER) {
	        super(collisionGroup, canCollideWith);
	        this._isKinematic = false;
	        this._mass = 1.0;
	        this._gravity = new Vector3(0, -10, 0);
	        this._angularDamping = 0.0;
	        this._linearDamping = 0.0;
	        this._overrideGravity = false;
	        this._totalTorque = new Vector3(0, 0, 0);
	        this._totalForce = new Vector3(0, 0, 0);
	        this._linearVelocity = new Vector3();
	        this._angularVelocity = new Vector3();
	        this._linearFactor = new Vector3(1, 1, 1);
	        this._angularFactor = new Vector3(1, 1, 1);
	        this._detectCollisions = true;
	    }
	    static __init__() {
	        Rigidbody3D._nativeTempVector30 = new Physics3D._physics3D.btVector3(0, 0, 0);
	        Rigidbody3D._nativeTempVector31 = new Physics3D._physics3D.btVector3(0, 0, 0);
	        Rigidbody3D._nativeVector3Zero = new Physics3D._physics3D.btVector3(0, 0, 0);
	        Rigidbody3D._nativeInertia = new Physics3D._physics3D.btVector3(0, 0, 0);
	        Rigidbody3D._nativeImpulse = new Physics3D._physics3D.btVector3(0, 0, 0);
	        Rigidbody3D._nativeImpulseOffset = new Physics3D._physics3D.btVector3(0, 0, 0);
	        Rigidbody3D._nativeGravity = new Physics3D._physics3D.btVector3(0, 0, 0);
	    }
	    get mass() {
	        return this._mass;
	    }
	    set mass(value) {
	        value = Math.max(value, 1e-07);
	        this._mass = value;
	        (this._isKinematic) || (this._updateMass(value));
	    }
	    get isKinematic() {
	        return this._isKinematic;
	    }
	    set isKinematic(value) {
	        this._isKinematic = value;
	        var canInSimulation = !!(this._simulation && this._enabled && this._colliderShape);
	        canInSimulation && this._removeFromSimulation();
	        var natColObj = this._nativeColliderObject;
	        var flags = natColObj.getCollisionFlags();
	        if (value) {
	            flags = flags | PhysicsComponent.COLLISIONFLAGS_KINEMATIC_OBJECT;
	            natColObj.setCollisionFlags(flags);
	            this._nativeColliderObject.forceActivationState(PhysicsComponent.ACTIVATIONSTATE_DISABLE_DEACTIVATION);
	            this._enableProcessCollisions = false;
	            this._updateMass(0);
	        }
	        else {
	            if ((flags & PhysicsComponent.COLLISIONFLAGS_KINEMATIC_OBJECT) > 0)
	                flags = flags ^ PhysicsComponent.COLLISIONFLAGS_KINEMATIC_OBJECT;
	            natColObj.setCollisionFlags(flags);
	            this._nativeColliderObject.setActivationState(PhysicsComponent.ACTIVATIONSTATE_ACTIVE_TAG);
	            this._enableProcessCollisions = true;
	            this._updateMass(this._mass);
	        }
	        var nativeZero = Rigidbody3D._nativeVector3Zero;
	        natColObj.setInterpolationLinearVelocity(nativeZero);
	        natColObj.setLinearVelocity(nativeZero);
	        natColObj.setInterpolationAngularVelocity(nativeZero);
	        natColObj.setAngularVelocity(nativeZero);
	        canInSimulation && this._addToSimulation();
	    }
	    get linearDamping() {
	        return this._linearDamping;
	    }
	    set linearDamping(value) {
	        this._linearDamping = value;
	        if (this._nativeColliderObject)
	            this._nativeColliderObject.setDamping(value, this._angularDamping);
	    }
	    get angularDamping() {
	        return this._angularDamping;
	    }
	    set angularDamping(value) {
	        this._angularDamping = value;
	        if (this._nativeColliderObject)
	            this._nativeColliderObject.setDamping(this._linearDamping, value);
	    }
	    get overrideGravity() {
	        return this._overrideGravity;
	    }
	    set overrideGravity(value) {
	        this._overrideGravity = value;
	        if (this._nativeColliderObject) {
	            var flag = this._nativeColliderObject.getFlags();
	            if (value) {
	                if ((flag & Rigidbody3D._BT_DISABLE_WORLD_GRAVITY) === 0)
	                    this._nativeColliderObject.setFlags(flag | Rigidbody3D._BT_DISABLE_WORLD_GRAVITY);
	            }
	            else {
	                if ((flag & Rigidbody3D._BT_DISABLE_WORLD_GRAVITY) > 0)
	                    this._nativeColliderObject.setFlags(flag ^ Rigidbody3D._BT_DISABLE_WORLD_GRAVITY);
	            }
	        }
	    }
	    get gravity() {
	        return this._gravity;
	    }
	    set gravity(value) {
	        this._gravity = value;
	        Rigidbody3D._nativeGravity.setValue(-value.x, value.y, value.z);
	        this._nativeColliderObject.setGravity(Rigidbody3D._nativeGravity);
	    }
	    get totalForce() {
	        if (this._nativeColliderObject) {
	            var nativeTotalForce = this._nativeColliderObject.getTotalForce();
	            Utils3D._convertToLayaVec3(nativeTotalForce, this._totalForce, true);
	            return this._totalForce;
	        }
	        return null;
	    }
	    get linearFactor() {
	        if (this._nativeColliderObject)
	            return this._linearFactor;
	        return null;
	    }
	    set linearFactor(value) {
	        this._linearFactor = value;
	        if (this._nativeColliderObject) {
	            var nativeValue = Rigidbody3D._nativeTempVector30;
	            Utils3D._convertToBulletVec3(value, nativeValue, false);
	            this._nativeColliderObject.setLinearFactor(nativeValue);
	        }
	    }
	    get linearVelocity() {
	        if (this._nativeColliderObject)
	            Utils3D._convertToLayaVec3(this._nativeColliderObject.getLinearVelocity(), this._linearVelocity, true);
	        return this._linearVelocity;
	    }
	    set linearVelocity(value) {
	        this._linearVelocity = value;
	        if (this._nativeColliderObject) {
	            var nativeValue = Rigidbody3D._nativeTempVector30;
	            Utils3D._convertToBulletVec3(value, nativeValue, true);
	            (this.isSleeping) && (this.wakeUp());
	            this._nativeColliderObject.setLinearVelocity(nativeValue);
	        }
	    }
	    get angularFactor() {
	        if (this._nativeColliderObject)
	            return this._angularFactor;
	        return null;
	    }
	    set angularFactor(value) {
	        this._angularFactor = value;
	        if (this._nativeColliderObject) {
	            var nativeValue = Rigidbody3D._nativeTempVector30;
	            Utils3D._convertToBulletVec3(value, nativeValue, false);
	            this._nativeColliderObject.setAngularFactor(nativeValue);
	        }
	    }
	    get angularVelocity() {
	        if (this._nativeColliderObject)
	            Utils3D._convertToLayaVec3(this._nativeColliderObject.getAngularVelocity(), this._angularVelocity, true);
	        return this._angularVelocity;
	    }
	    set angularVelocity(value) {
	        this._angularVelocity = value;
	        if (this._nativeColliderObject) {
	            var nativeValue = Rigidbody3D._nativeTempVector30;
	            Utils3D._convertToBulletVec3(value, nativeValue, true);
	            (this.isSleeping) && (this.wakeUp());
	            this._nativeColliderObject.setAngularVelocity(nativeValue);
	        }
	    }
	    get totalTorque() {
	        if (this._nativeColliderObject) {
	            var nativeTotalTorque = this._nativeColliderObject.getTotalTorque();
	            Utils3D._convertToLayaVec3(nativeTotalTorque, this._totalTorque, true);
	            return this._totalTorque;
	        }
	        return null;
	    }
	    get detectCollisions() {
	        return this._detectCollisions;
	    }
	    set detectCollisions(value) {
	        if (this._detectCollisions !== value) {
	            this._detectCollisions = value;
	            if (this._colliderShape && this._enabled && this._simulation) {
	                this._simulation._removeRigidBody(this);
	                this._simulation._addRigidBody(this, this._collisionGroup, value ? this._canCollideWith : 0);
	            }
	        }
	    }
	    get isSleeping() {
	        if (this._nativeColliderObject)
	            return this._nativeColliderObject.getActivationState() === PhysicsComponent.ACTIVATIONSTATE_ISLAND_SLEEPING;
	        return false;
	    }
	    get sleepLinearVelocity() {
	        return this._nativeColliderObject.getLinearSleepingThreshold();
	    }
	    set sleepLinearVelocity(value) {
	        this._nativeColliderObject.setSleepingThresholds(value, this._nativeColliderObject.getAngularSleepingThreshold());
	    }
	    get sleepAngularVelocity() {
	        return this._nativeColliderObject.getAngularSleepingThreshold();
	    }
	    set sleepAngularVelocity(value) {
	        this._nativeColliderObject.setSleepingThresholds(this._nativeColliderObject.getLinearSleepingThreshold(), value);
	    }
	    _updateMass(mass) {
	        if (this._nativeColliderObject && this._colliderShape) {
	            this._colliderShape._nativeShape.calculateLocalInertia(mass, Rigidbody3D._nativeInertia);
	            this._nativeColliderObject.setMassProps(mass, Rigidbody3D._nativeInertia);
	            this._nativeColliderObject.updateInertiaTensor();
	        }
	    }
	    _delegateMotionStateGetWorldTransform(worldTransPointer) {
	    }
	    _delegateMotionStateSetWorldTransform(worldTransPointer) {
	        var rigidBody = this._rigidbody;
	        rigidBody._simulation._updatedRigidbodies++;
	        var physics3D = Physics3D._physics3D;
	        var worldTrans = physics3D.wrapPointer(worldTransPointer, physics3D.btTransform);
	        rigidBody._updateTransformComponent(worldTrans);
	    }
	    _delegateMotionStateGetWorldTransformNative(ridgidBody3D, worldTransPointer) {
	    }
	    _delegateMotionStateSetWorldTransformNative(rigidBody3D, worldTransPointer) {
	        var rigidBody = rigidBody3D;
	        rigidBody._simulation._updatedRigidbodies++;
	        var physics3D = Physics3D._physics3D;
	        var worldTrans = physics3D.wrapPointer(worldTransPointer, physics3D.btTransform);
	        rigidBody._updateTransformComponent(worldTrans);
	    }
	    _onScaleChange(scale) {
	        super._onScaleChange(scale);
	        this._updateMass(this._isKinematic ? 0 : this._mass);
	    }
	    _delegateMotionStateClear() {
	        this._rigidbody = null;
	    }
	    _onAdded() {
	        var physics3D = Physics3D._physics3D;
	        var motionState = new physics3D.LayaMotionState();
	        var isConchApp = (window.conch != null);
	        if (isConchApp && physics3D.LayaMotionState.prototype.setRigidbody) {
	            motionState.setRigidbody(this);
	            motionState.setNativeGetWorldTransform(this._delegateMotionStateGetWorldTransformNative);
	            motionState.setNativeSetWorldTransform(this._delegateMotionStateSetWorldTransformNative);
	        }
	        else {
	            motionState.getWorldTransform = this._delegateMotionStateGetWorldTransform;
	            motionState.setWorldTransform = this._delegateMotionStateSetWorldTransform;
	        }
	        motionState.clear = this._delegateMotionStateClear;
	        motionState._rigidbody = this;
	        this._nativeMotionState = motionState;
	        var constructInfo = new physics3D.btRigidBodyConstructionInfo(0.0, motionState, null, Rigidbody3D._nativeVector3Zero);
	        var btRigid = new physics3D.btRigidBody(constructInfo);
	        btRigid.setUserIndex(this.id);
	        this._nativeColliderObject = btRigid;
	        super._onAdded();
	        this.mass = this._mass;
	        this.linearFactor = this._linearFactor;
	        this.angularFactor = this._angularFactor;
	        this.linearDamping = this._linearDamping;
	        this.angularDamping = this._angularDamping;
	        this.overrideGravity = this._overrideGravity;
	        this.gravity = this._gravity;
	        this.isKinematic = this._isKinematic;
	        physics3D.destroy(constructInfo);
	    }
	    _onShapeChange(colShape) {
	        super._onShapeChange(colShape);
	        if (this._isKinematic) {
	            this._updateMass(0);
	        }
	        else {
	            this._nativeColliderObject.setCenterOfMassTransform(this._nativeColliderObject.getWorldTransform());
	            this._updateMass(this._mass);
	        }
	    }
	    _parse(data) {
	        (data.friction != null) && (this.friction = data.friction);
	        (data.rollingFriction != null) && (this.rollingFriction = data.rollingFriction);
	        (data.restitution != null) && (this.restitution = data.restitution);
	        (data.isTrigger != null) && (this.isTrigger = data.isTrigger);
	        (data.mass != null) && (this.mass = data.mass);
	        (data.isKinematic != null) && (this.isKinematic = data.isKinematic);
	        (data.linearDamping != null) && (this.linearDamping = data.linearDamping);
	        (data.angularDamping != null) && (this.angularDamping = data.angularDamping);
	        (data.overrideGravity != null) && (this.overrideGravity = data.overrideGravity);
	        if (data.gravity) {
	            this.gravity.fromArray(data.gravity);
	            this.gravity = this.gravity;
	        }
	        super._parse(data);
	        this._parseShape(data.shapes);
	    }
	    _onDestroy() {
	        var physics3D = Physics3D._physics3D;
	        this._nativeMotionState.clear();
	        physics3D.destroy(this._nativeMotionState);
	        super._onDestroy();
	        this._nativeMotionState = null;
	        this._gravity = null;
	        this._totalTorque = null;
	        this._linearVelocity = null;
	        this._angularVelocity = null;
	        this._linearFactor = null;
	        this._angularFactor = null;
	    }
	    _addToSimulation() {
	        this._simulation._addRigidBody(this, this._collisionGroup, this._detectCollisions ? this._canCollideWith : 0);
	    }
	    _removeFromSimulation() {
	        this._simulation._removeRigidBody(this);
	    }
	    _cloneTo(dest) {
	        super._cloneTo(dest);
	        var destRigidbody3D = dest;
	        destRigidbody3D.isKinematic = this._isKinematic;
	        destRigidbody3D.mass = this._mass;
	        destRigidbody3D.gravity = this._gravity;
	        destRigidbody3D.angularDamping = this._angularDamping;
	        destRigidbody3D.linearDamping = this._linearDamping;
	        destRigidbody3D.overrideGravity = this._overrideGravity;
	        destRigidbody3D.linearVelocity = this._linearVelocity;
	        destRigidbody3D.angularVelocity = this._angularVelocity;
	        destRigidbody3D.linearFactor = this._linearFactor;
	        destRigidbody3D.angularFactor = this._angularFactor;
	        destRigidbody3D.detectCollisions = this._detectCollisions;
	    }
	    applyForce(force, localOffset = null) {
	        if (this._nativeColliderObject == null)
	            throw "Attempted to call a Physics function that is avaliable only when the Entity has been already added to the Scene.";
	        var nativeForce = Rigidbody3D._nativeTempVector30;
	        nativeForce.setValue(-force.x, force.y, force.z);
	        if (localOffset) {
	            var nativeOffset = Rigidbody3D._nativeTempVector31;
	            nativeOffset.setValue(-localOffset.x, localOffset.y, localOffset.z);
	            this._nativeColliderObject.applyForce(nativeForce, nativeOffset);
	        }
	        else {
	            this._nativeColliderObject.applyCentralForce(nativeForce);
	        }
	    }
	    applyTorque(torque) {
	        if (this._nativeColliderObject == null)
	            throw "Attempted to call a Physics function that is avaliable only when the Entity has been already added to the Scene.";
	        var nativeTorque = Rigidbody3D._nativeTempVector30;
	        nativeTorque.setValue(-torque.x, torque.y, torque.z);
	        this._nativeColliderObject.applyTorque(nativeTorque);
	    }
	    applyImpulse(impulse, localOffset = null) {
	        if (this._nativeColliderObject == null)
	            throw "Attempted to call a Physics function that is avaliable only when the Entity has been already added to the Scene.";
	        Rigidbody3D._nativeImpulse.setValue(-impulse.x, impulse.y, impulse.z);
	        if (localOffset) {
	            Rigidbody3D._nativeImpulseOffset.setValue(-localOffset.x, localOffset.y, localOffset.z);
	            this._nativeColliderObject.applyImpulse(Rigidbody3D._nativeImpulse, Rigidbody3D._nativeImpulseOffset);
	        }
	        else {
	            this._nativeColliderObject.applyCentralImpulse(Rigidbody3D._nativeImpulse);
	        }
	    }
	    applyTorqueImpulse(torqueImpulse) {
	        if (this._nativeColliderObject == null)
	            throw "Attempted to call a Physics function that is avaliable only when the Entity has been already added to the Scene.";
	        var nativeTorqueImpulse = Rigidbody3D._nativeTempVector30;
	        nativeTorqueImpulse.setValue(-torqueImpulse.x, torqueImpulse.y, torqueImpulse.z);
	        this._nativeColliderObject.applyTorqueImpulse(nativeTorqueImpulse);
	    }
	    wakeUp() {
	        this._nativeColliderObject && (this._nativeColliderObject.activate(false));
	    }
	    clearForces() {
	        var rigidBody = this._nativeColliderObject;
	        if (rigidBody == null)
	            throw "Attempted to call a Physics function that is avaliable only when the Entity has been already added to the Scene.";
	        rigidBody.clearForces();
	        var nativeZero = Rigidbody3D._nativeVector3Zero;
	        rigidBody.setInterpolationLinearVelocity(nativeZero);
	        rigidBody.setLinearVelocity(nativeZero);
	        rigidBody.setInterpolationAngularVelocity(nativeZero);
	        rigidBody.setAngularVelocity(nativeZero);
	    }
	}
	Rigidbody3D.TYPE_STATIC = 0;
	Rigidbody3D.TYPE_DYNAMIC = 1;
	Rigidbody3D.TYPE_KINEMATIC = 2;
	Rigidbody3D._BT_DISABLE_WORLD_GRAVITY = 1;
	Rigidbody3D._BT_ENABLE_GYROPSCOPIC_FORCE = 2;

	class StaticPlaneColliderShape extends ColliderShape {
	    static __init__() {
	        StaticPlaneColliderShape._nativeNormal = new Physics3D._physics3D.btVector3(0, 0, 0);
	    }
	    constructor(normal, offset) {
	        super();
	        this._normal = normal;
	        this._offset = offset;
	        this._type = ColliderShape.SHAPETYPES_STATICPLANE;
	        StaticPlaneColliderShape._nativeNormal.setValue(-normal.x, normal.y, normal.z);
	        this._nativeShape = new Physics3D._physics3D.btStaticPlaneShape(StaticPlaneColliderShape._nativeNormal, offset);
	    }
	    clone() {
	        var dest = new StaticPlaneColliderShape(this._normal, this._offset);
	        this.cloneTo(dest);
	        return dest;
	    }
	}

	class SubMesh extends GeometryElement {
	    constructor(mesh) {
	        super();
	        this._id = ++SubMesh._uniqueIDCounter;
	        this._mesh = mesh;
	        this._boneIndicesList = [];
	        this._subIndexBufferStart = [];
	        this._subIndexBufferCount = [];
	    }
	    get indexCount() {
	        return this._indexCount;
	    }
	    _setIndexRange(indexStart, indexCount) {
	        this._indexStart = indexStart;
	        this._indexCount = indexCount;
	        this._indices = new Uint16Array(this._indexBuffer.getData().buffer, indexStart * 2, indexCount);
	    }
	    _getType() {
	        return SubMesh._type;
	    }
	    _prepareRender(state) {
	        this._mesh._uploadVerticesData();
	        return true;
	    }
	    _render(state) {
	        var gl = Laya.LayaGL.instance;
	        this._mesh._bufferState.bind();
	        var skinnedDatas = state.renderElement.render._skinnedData;
	        if (skinnedDatas) {
	            var subSkinnedDatas = skinnedDatas[this._indexInMesh];
	            var boneIndicesListCount = this._boneIndicesList.length;
	            for (var i = 0; i < boneIndicesListCount; i++) {
	                state.shader.uploadCustomUniform(SkinnedMeshSprite3D.BONES, subSkinnedDatas[i]);
	                gl.drawElements(gl.TRIANGLES, this._subIndexBufferCount[i], gl.UNSIGNED_SHORT, this._subIndexBufferStart[i] * 2);
	            }
	        }
	        else {
	            gl.drawElements(gl.TRIANGLES, this._indexCount, gl.UNSIGNED_SHORT, this._indexStart * 2);
	        }
	        Laya.Stat.trianglesFaces += this._indexCount / 3;
	        Laya.Stat.renderBatches++;
	    }
	    getIndices() {
	        if (this._mesh._isReadable)
	            return this._indices.slice();
	        else
	            throw "SubMesh:can't get indices on subMesh,mesh's isReadable must be true.";
	    }
	    setIndices(indices) {
	        this._indexBuffer.setData(indices, this._indexStart, 0, this._indexCount);
	    }
	    destroy() {
	        if (this._destroyed)
	            return;
	        super.destroy();
	        this._indexBuffer.destroy();
	        this._indexBuffer = null;
	        this._mesh = null;
	        this._boneIndicesList = null;
	        this._subIndexBufferStart = null;
	        this._subIndexBufferCount = null;
	        this._skinAnimationDatas = null;
	    }
	}
	SubMesh._uniqueIDCounter = 0;
	SubMesh._type = GeometryElement._typeCounter++;

	class LoadModelV04 {
	    static parse(readData, version, mesh, subMeshes) {
	        LoadModelV04._mesh = mesh;
	        LoadModelV04._subMeshes = subMeshes;
	        LoadModelV04._version = version;
	        LoadModelV04._readData = readData;
	        LoadModelV04.READ_DATA();
	        LoadModelV04.READ_BLOCK();
	        LoadModelV04.READ_STRINGS();
	        for (var i = 0, n = LoadModelV04._BLOCK.count; i < n; i++) {
	            LoadModelV04._readData.pos = LoadModelV04._BLOCK.blockStarts[i];
	            var index = LoadModelV04._readData.getUint16();
	            var blockName = LoadModelV04._strings[index];
	            var fn = LoadModelV04["READ_" + blockName];
	            if (fn == null)
	                throw new Error("model file err,no this function:" + index + " " + blockName);
	            else
	                fn.call(null);
	        }
	        LoadModelV04._mesh._bindPoseIndices = new Uint16Array(LoadModelV04._bindPoseIndices);
	        LoadModelV04._bindPoseIndices.length = 0;
	        LoadModelV04._strings.length = 0;
	        LoadModelV04._readData = null;
	        LoadModelV04._version = null;
	        LoadModelV04._mesh = null;
	        LoadModelV04._subMeshes = null;
	    }
	    static _readString() {
	        return LoadModelV04._strings[LoadModelV04._readData.getUint16()];
	    }
	    static READ_DATA() {
	        LoadModelV04._DATA.offset = LoadModelV04._readData.getUint32();
	        LoadModelV04._DATA.size = LoadModelV04._readData.getUint32();
	    }
	    static READ_BLOCK() {
	        var count = LoadModelV04._BLOCK.count = LoadModelV04._readData.getUint16();
	        var blockStarts = LoadModelV04._BLOCK.blockStarts = [];
	        var blockLengths = LoadModelV04._BLOCK.blockLengths = [];
	        for (var i = 0; i < count; i++) {
	            blockStarts.push(LoadModelV04._readData.getUint32());
	            blockLengths.push(LoadModelV04._readData.getUint32());
	        }
	    }
	    static READ_STRINGS() {
	        var offset = LoadModelV04._readData.getUint32();
	        var count = LoadModelV04._readData.getUint16();
	        var prePos = LoadModelV04._readData.pos;
	        LoadModelV04._readData.pos = offset + LoadModelV04._DATA.offset;
	        for (var i = 0; i < count; i++)
	            LoadModelV04._strings[i] = LoadModelV04._readData.readUTFString();
	        LoadModelV04._readData.pos = prePos;
	    }
	    static READ_MESH() {
	        var gl = Laya.LayaGL.instance;
	        var name = LoadModelV04._readString();
	        var arrayBuffer = LoadModelV04._readData.__getBuffer();
	        var i;
	        var memorySize = 0;
	        var vertexBufferCount = LoadModelV04._readData.getInt16();
	        var offset = LoadModelV04._DATA.offset;
	        for (i = 0; i < vertexBufferCount; i++) {
	            var vbStart = offset + LoadModelV04._readData.getUint32();
	            var vbLength = LoadModelV04._readData.getUint32();
	            var vbArrayBuffer = arrayBuffer.slice(vbStart, vbStart + vbLength);
	            var vbDatas = new Float32Array(vbArrayBuffer);
	            var bufferAttribute = LoadModelV04._readString();
	            var vertexDeclaration;
	            switch (LoadModelV04._version) {
	                case "LAYAMODEL:0301":
	                case "LAYAMODEL:0400":
	                    vertexDeclaration = VertexMesh.getVertexDeclaration(bufferAttribute);
	                    break;
	                case "LAYAMODEL:0401":
	                    vertexDeclaration = VertexMesh.getVertexDeclaration(bufferAttribute, false);
	                    break;
	                default:
	                    throw new Error("LoadModelV03: unknown version.");
	            }
	            if (!vertexDeclaration)
	                throw new Error("LoadModelV03: unknown vertexDeclaration.");
	            var vertexBuffer = new VertexBuffer3D(vbDatas.length * 4, gl.STATIC_DRAW, true);
	            vertexBuffer.vertexDeclaration = vertexDeclaration;
	            vertexBuffer.setData(vbDatas.buffer);
	            LoadModelV04._mesh._vertexBuffer = vertexBuffer;
	            LoadModelV04._mesh._vertexCount += vertexBuffer._byteLength / vertexDeclaration.vertexStride;
	            memorySize += vbDatas.length * 4;
	        }
	        var ibStart = offset + LoadModelV04._readData.getUint32();
	        var ibLength = LoadModelV04._readData.getUint32();
	        var ibDatas = new Uint16Array(arrayBuffer.slice(ibStart, ibStart + ibLength));
	        var indexBuffer = new IndexBuffer3D(IndexBuffer3D.INDEXTYPE_USHORT, ibLength / 2, gl.STATIC_DRAW, true);
	        indexBuffer.setData(ibDatas);
	        LoadModelV04._mesh._indexBuffer = indexBuffer;
	        memorySize += indexBuffer.indexCount * 2;
	        LoadModelV04._mesh._setBuffer(LoadModelV04._mesh._vertexBuffer, indexBuffer);
	        LoadModelV04._mesh._setCPUMemory(memorySize);
	        LoadModelV04._mesh._setGPUMemory(memorySize);
	        var boneNames = LoadModelV04._mesh._boneNames = [];
	        var boneCount = LoadModelV04._readData.getUint16();
	        boneNames.length = boneCount;
	        for (i = 0; i < boneCount; i++)
	            boneNames[i] = LoadModelV04._strings[LoadModelV04._readData.getUint16()];
	        LoadModelV04._readData.pos += 8;
	        var bindPoseDataStart = LoadModelV04._readData.getUint32();
	        var bindPoseDataLength = LoadModelV04._readData.getUint32();
	        var bindPoseDatas = new Float32Array(arrayBuffer.slice(offset + bindPoseDataStart, offset + bindPoseDataStart + bindPoseDataLength));
	        var bindPoseFloatCount = bindPoseDatas.length;
	        var bindPoseBuffer = LoadModelV04._mesh._inverseBindPosesBuffer = new ArrayBuffer(bindPoseFloatCount * 4);
	        LoadModelV04._mesh._inverseBindPoses = [];
	        for (i = 0; i < bindPoseFloatCount; i += 16) {
	            var inverseGlobalBindPose = new Matrix4x4(bindPoseDatas[i + 0], bindPoseDatas[i + 1], bindPoseDatas[i + 2], bindPoseDatas[i + 3], bindPoseDatas[i + 4], bindPoseDatas[i + 5], bindPoseDatas[i + 6], bindPoseDatas[i + 7], bindPoseDatas[i + 8], bindPoseDatas[i + 9], bindPoseDatas[i + 10], bindPoseDatas[i + 11], bindPoseDatas[i + 12], bindPoseDatas[i + 13], bindPoseDatas[i + 14], bindPoseDatas[i + 15], new Float32Array(bindPoseBuffer, i * 4, 16));
	            LoadModelV04._mesh._inverseBindPoses[i / 16] = inverseGlobalBindPose;
	        }
	        return true;
	    }
	    static READ_SUBMESH() {
	        var arrayBuffer = LoadModelV04._readData.__getBuffer();
	        var subMesh = new SubMesh(LoadModelV04._mesh);
	        LoadModelV04._readData.getInt16();
	        LoadModelV04._readData.getUint32();
	        LoadModelV04._readData.getUint32();
	        var ibStart = LoadModelV04._readData.getUint32();
	        var ibCount = LoadModelV04._readData.getUint32();
	        var indexBuffer = LoadModelV04._mesh._indexBuffer;
	        subMesh._indexBuffer = indexBuffer;
	        subMesh._setIndexRange(ibStart, ibCount);
	        var vertexBuffer = LoadModelV04._mesh._vertexBuffer;
	        subMesh._vertexBuffer = vertexBuffer;
	        var offset = LoadModelV04._DATA.offset;
	        var subIndexBufferStart = subMesh._subIndexBufferStart;
	        var subIndexBufferCount = subMesh._subIndexBufferCount;
	        var boneIndicesList = subMesh._boneIndicesList;
	        var drawCount = LoadModelV04._readData.getUint16();
	        subIndexBufferStart.length = drawCount;
	        subIndexBufferCount.length = drawCount;
	        boneIndicesList.length = drawCount;
	        var pathMarks = LoadModelV04._mesh._skinDataPathMarks;
	        var bindPoseIndices = LoadModelV04._bindPoseIndices;
	        var subMeshIndex = LoadModelV04._subMeshes.length;
	        for (var i = 0; i < drawCount; i++) {
	            subIndexBufferStart[i] = LoadModelV04._readData.getUint32();
	            subIndexBufferCount[i] = LoadModelV04._readData.getUint32();
	            var boneDicofs = LoadModelV04._readData.getUint32();
	            var boneDicCount = LoadModelV04._readData.getUint32();
	            var boneIndices = boneIndicesList[i] = new Uint16Array(arrayBuffer.slice(offset + boneDicofs, offset + boneDicofs + boneDicCount));
	            for (var j = 0, m = boneIndices.length; j < m; j++) {
	                var index = boneIndices[j];
	                var combineIndex = bindPoseIndices.indexOf(index);
	                if (combineIndex === -1) {
	                    boneIndices[j] = bindPoseIndices.length;
	                    bindPoseIndices.push(index);
	                    pathMarks.push([subMeshIndex, i, j]);
	                }
	                else {
	                    boneIndices[j] = combineIndex;
	                }
	            }
	        }
	        LoadModelV04._subMeshes.push(subMesh);
	        return true;
	    }
	}
	LoadModelV04._BLOCK = { count: 0 };
	LoadModelV04._DATA = { offset: 0, size: 0 };
	LoadModelV04._strings = [];
	LoadModelV04._bindPoseIndices = [];

	class LoadModelV05 {
	    static parse(readData, version, mesh, subMeshes) {
	        LoadModelV05._mesh = mesh;
	        LoadModelV05._subMeshes = subMeshes;
	        LoadModelV05._version = version;
	        LoadModelV05._readData = readData;
	        LoadModelV05.READ_DATA();
	        LoadModelV05.READ_BLOCK();
	        LoadModelV05.READ_STRINGS();
	        for (var i = 0, n = LoadModelV05._BLOCK.count; i < n; i++) {
	            LoadModelV05._readData.pos = LoadModelV05._BLOCK.blockStarts[i];
	            var index = LoadModelV05._readData.getUint16();
	            var blockName = LoadModelV05._strings[index];
	            var fn = LoadModelV05["READ_" + blockName];
	            if (fn == null)
	                throw new Error("model file err,no this function:" + index + " " + blockName);
	            else
	                fn.call(null);
	        }
	        LoadModelV05._mesh._bindPoseIndices = new Uint16Array(LoadModelV05._bindPoseIndices);
	        LoadModelV05._bindPoseIndices.length = 0;
	        LoadModelV05._strings.length = 0;
	        LoadModelV05._readData = null;
	        LoadModelV05._version = null;
	        LoadModelV05._mesh = null;
	        LoadModelV05._subMeshes = null;
	    }
	    static _readString() {
	        return LoadModelV05._strings[LoadModelV05._readData.getUint16()];
	    }
	    static READ_DATA() {
	        LoadModelV05._DATA.offset = LoadModelV05._readData.getUint32();
	        LoadModelV05._DATA.size = LoadModelV05._readData.getUint32();
	    }
	    static READ_BLOCK() {
	        var count = LoadModelV05._BLOCK.count = LoadModelV05._readData.getUint16();
	        var blockStarts = LoadModelV05._BLOCK.blockStarts = [];
	        var blockLengths = LoadModelV05._BLOCK.blockLengths = [];
	        for (var i = 0; i < count; i++) {
	            blockStarts.push(LoadModelV05._readData.getUint32());
	            blockLengths.push(LoadModelV05._readData.getUint32());
	        }
	    }
	    static READ_STRINGS() {
	        var offset = LoadModelV05._readData.getUint32();
	        var count = LoadModelV05._readData.getUint16();
	        var prePos = LoadModelV05._readData.pos;
	        LoadModelV05._readData.pos = offset + LoadModelV05._DATA.offset;
	        for (var i = 0; i < count; i++)
	            LoadModelV05._strings[i] = LoadModelV05._readData.readUTFString();
	        LoadModelV05._readData.pos = prePos;
	    }
	    static READ_MESH() {
	        var gl = Laya.LayaGL.instance;
	        var i;
	        var memorySize = 0;
	        var name = LoadModelV05._readString();
	        var arrayBuffer = LoadModelV05._readData.__getBuffer();
	        var vertexBufferCount = LoadModelV05._readData.getInt16();
	        var offset = LoadModelV05._DATA.offset;
	        for (i = 0; i < vertexBufferCount; i++) {
	            var vbStart = offset + LoadModelV05._readData.getUint32();
	            var vertexCount = LoadModelV05._readData.getUint32();
	            var vertexFlag = LoadModelV05._readString();
	            var vertexDeclaration = VertexMesh.getVertexDeclaration(vertexFlag, false);
	            var vertexStride = vertexDeclaration.vertexStride;
	            var vertexData;
	            var floatData;
	            var uint8Data;
	            var subVertexFlags = vertexFlag.split(",");
	            var subVertexCount = subVertexFlags.length;
	            switch (LoadModelV05._version) {
	                case "LAYAMODEL:05":
	                    vertexData = arrayBuffer.slice(vbStart, vbStart + vertexCount * vertexStride);
	                    floatData = new Float32Array(vertexData);
	                    uint8Data = new Uint8Array(vertexData);
	                    break;
	                case "LAYAMODEL:COMPRESSION_05":
	                    vertexData = new ArrayBuffer(vertexStride * vertexCount);
	                    floatData = new Float32Array(vertexData);
	                    uint8Data = new Uint8Array(vertexData);
	                    var lastPosition = LoadModelV05._readData.pos;
	                    LoadModelV05._readData.pos = vbStart;
	                    for (var j = 0; j < vertexCount; j++) {
	                        var subOffset;
	                        var verOffset = j * vertexStride;
	                        for (var k = 0; k < subVertexCount; k++) {
	                            switch (subVertexFlags[k]) {
	                                case "POSITION":
	                                    subOffset = verOffset / 4;
	                                    floatData[subOffset] = HalfFloatUtils.convertToNumber(LoadModelV05._readData.getUint16());
	                                    floatData[subOffset + 1] = HalfFloatUtils.convertToNumber(LoadModelV05._readData.getUint16());
	                                    floatData[subOffset + 2] = HalfFloatUtils.convertToNumber(LoadModelV05._readData.getUint16());
	                                    verOffset += 12;
	                                    break;
	                                case "NORMAL":
	                                    subOffset = verOffset / 4;
	                                    floatData[subOffset] = LoadModelV05._readData.getUint8() / 127.5 - 1;
	                                    floatData[subOffset + 1] = LoadModelV05._readData.getUint8() / 127.5 - 1;
	                                    floatData[subOffset + 2] = LoadModelV05._readData.getUint8() / 127.5 - 1;
	                                    verOffset += 12;
	                                    break;
	                                case "COLOR":
	                                    subOffset = verOffset / 4;
	                                    floatData[subOffset] = LoadModelV05._readData.getUint8() / 255;
	                                    floatData[subOffset + 1] = LoadModelV05._readData.getUint8() / 255;
	                                    floatData[subOffset + 2] = LoadModelV05._readData.getUint8() / 255;
	                                    floatData[subOffset + 3] = LoadModelV05._readData.getUint8() / 255;
	                                    verOffset += 16;
	                                    break;
	                                case "UV":
	                                    subOffset = verOffset / 4;
	                                    floatData[subOffset] = HalfFloatUtils.convertToNumber(LoadModelV05._readData.getUint16());
	                                    floatData[subOffset + 1] = HalfFloatUtils.convertToNumber(LoadModelV05._readData.getUint16());
	                                    verOffset += 8;
	                                    break;
	                                case "UV1":
	                                    subOffset = verOffset / 4;
	                                    floatData[subOffset] = HalfFloatUtils.convertToNumber(LoadModelV05._readData.getUint16());
	                                    floatData[subOffset + 1] = HalfFloatUtils.convertToNumber(LoadModelV05._readData.getUint16());
	                                    verOffset += 8;
	                                    break;
	                                case "BLENDWEIGHT":
	                                    subOffset = verOffset / 4;
	                                    floatData[subOffset] = LoadModelV05._readData.getUint8() / 255;
	                                    floatData[subOffset + 1] = LoadModelV05._readData.getUint8() / 255;
	                                    floatData[subOffset + 2] = LoadModelV05._readData.getUint8() / 255;
	                                    floatData[subOffset + 3] = LoadModelV05._readData.getUint8() / 255;
	                                    verOffset += 16;
	                                    break;
	                                case "BLENDINDICES":
	                                    uint8Data[verOffset] = LoadModelV05._readData.getUint8();
	                                    uint8Data[verOffset + 1] = LoadModelV05._readData.getUint8();
	                                    uint8Data[verOffset + 2] = LoadModelV05._readData.getUint8();
	                                    uint8Data[verOffset + 3] = LoadModelV05._readData.getUint8();
	                                    verOffset += 4;
	                                    break;
	                                case "TANGENT":
	                                    subOffset = verOffset / 4;
	                                    floatData[subOffset] = LoadModelV05._readData.getUint8() / 127.5 - 1;
	                                    floatData[subOffset + 1] = LoadModelV05._readData.getUint8() / 127.5 - 1;
	                                    floatData[subOffset + 2] = LoadModelV05._readData.getUint8() / 127.5 - 1;
	                                    floatData[subOffset + 3] = LoadModelV05._readData.getUint8() / 127.5 - 1;
	                                    verOffset += 16;
	                                    break;
	                            }
	                        }
	                    }
	                    LoadModelV05._readData.pos = lastPosition;
	                    break;
	            }
	            var vertexBuffer = new VertexBuffer3D(vertexData.byteLength, gl.STATIC_DRAW, true);
	            vertexBuffer.vertexDeclaration = vertexDeclaration;
	            vertexBuffer.setData(vertexData);
	            LoadModelV05._mesh._vertexBuffer = vertexBuffer;
	            LoadModelV05._mesh._vertexCount += vertexBuffer._byteLength / vertexDeclaration.vertexStride;
	            memorySize += floatData.length * 4;
	        }
	        var ibStart = offset + LoadModelV05._readData.getUint32();
	        var ibLength = LoadModelV05._readData.getUint32();
	        var ibDatas = new Uint16Array(arrayBuffer.slice(ibStart, ibStart + ibLength));
	        var indexBuffer = new IndexBuffer3D(IndexBuffer3D.INDEXTYPE_USHORT, ibLength / 2, gl.STATIC_DRAW, true);
	        indexBuffer.setData(ibDatas);
	        LoadModelV05._mesh._indexBuffer = indexBuffer;
	        LoadModelV05._mesh._setBuffer(LoadModelV05._mesh._vertexBuffer, indexBuffer);
	        memorySize += indexBuffer.indexCount * 2;
	        LoadModelV05._mesh._setCPUMemory(memorySize);
	        LoadModelV05._mesh._setGPUMemory(memorySize);
	        var boneNames = LoadModelV05._mesh._boneNames = [];
	        var boneCount = LoadModelV05._readData.getUint16();
	        boneNames.length = boneCount;
	        for (i = 0; i < boneCount; i++)
	            boneNames[i] = LoadModelV05._strings[LoadModelV05._readData.getUint16()];
	        var bindPoseDataStart = LoadModelV05._readData.getUint32();
	        var bindPoseDataLength = LoadModelV05._readData.getUint32();
	        var bindPoseDatas = new Float32Array(arrayBuffer.slice(offset + bindPoseDataStart, offset + bindPoseDataStart + bindPoseDataLength));
	        var bindPoseFloatCount = bindPoseDatas.length;
	        var bindPoseBuffer = LoadModelV05._mesh._inverseBindPosesBuffer = new ArrayBuffer(bindPoseFloatCount * 4);
	        LoadModelV05._mesh._inverseBindPoses = [];
	        for (i = 0; i < bindPoseFloatCount; i += 16) {
	            var inverseGlobalBindPose = new Matrix4x4(bindPoseDatas[i + 0], bindPoseDatas[i + 1], bindPoseDatas[i + 2], bindPoseDatas[i + 3], bindPoseDatas[i + 4], bindPoseDatas[i + 5], bindPoseDatas[i + 6], bindPoseDatas[i + 7], bindPoseDatas[i + 8], bindPoseDatas[i + 9], bindPoseDatas[i + 10], bindPoseDatas[i + 11], bindPoseDatas[i + 12], bindPoseDatas[i + 13], bindPoseDatas[i + 14], bindPoseDatas[i + 15], new Float32Array(bindPoseBuffer, i * 4, 16));
	            LoadModelV05._mesh._inverseBindPoses[i / 16] = inverseGlobalBindPose;
	        }
	        return true;
	    }
	    static READ_SUBMESH() {
	        var arrayBuffer = LoadModelV05._readData.__getBuffer();
	        var subMesh = new SubMesh(LoadModelV05._mesh);
	        LoadModelV05._readData.getInt16();
	        var ibStart = LoadModelV05._readData.getUint32();
	        var ibCount = LoadModelV05._readData.getUint32();
	        var indexBuffer = LoadModelV05._mesh._indexBuffer;
	        subMesh._indexBuffer = indexBuffer;
	        subMesh._setIndexRange(ibStart, ibCount);
	        var vertexBuffer = LoadModelV05._mesh._vertexBuffer;
	        subMesh._vertexBuffer = vertexBuffer;
	        var offset = LoadModelV05._DATA.offset;
	        var subIndexBufferStart = subMesh._subIndexBufferStart;
	        var subIndexBufferCount = subMesh._subIndexBufferCount;
	        var boneIndicesList = subMesh._boneIndicesList;
	        var drawCount = LoadModelV05._readData.getUint16();
	        subIndexBufferStart.length = drawCount;
	        subIndexBufferCount.length = drawCount;
	        boneIndicesList.length = drawCount;
	        var pathMarks = LoadModelV05._mesh._skinDataPathMarks;
	        var bindPoseIndices = LoadModelV05._bindPoseIndices;
	        var subMeshIndex = LoadModelV05._subMeshes.length;
	        for (var i = 0; i < drawCount; i++) {
	            subIndexBufferStart[i] = LoadModelV05._readData.getUint32();
	            subIndexBufferCount[i] = LoadModelV05._readData.getUint32();
	            var boneDicofs = LoadModelV05._readData.getUint32();
	            var boneDicCount = LoadModelV05._readData.getUint32();
	            var boneIndices = boneIndicesList[i] = new Uint16Array(arrayBuffer.slice(offset + boneDicofs, offset + boneDicofs + boneDicCount));
	            for (var j = 0, m = boneIndices.length; j < m; j++) {
	                var index = boneIndices[j];
	                var combineIndex = bindPoseIndices.indexOf(index);
	                if (combineIndex === -1) {
	                    boneIndices[j] = bindPoseIndices.length;
	                    bindPoseIndices.push(index);
	                    pathMarks.push([subMeshIndex, i, j]);
	                }
	                else {
	                    boneIndices[j] = combineIndex;
	                }
	            }
	        }
	        LoadModelV05._subMeshes.push(subMesh);
	        return true;
	    }
	}
	LoadModelV05._BLOCK = { count: 0 };
	LoadModelV05._DATA = { offset: 0, size: 0 };
	LoadModelV05._strings = [];
	LoadModelV05._bindPoseIndices = [];

	class MeshReader {
	    constructor() {
	    }
	    static read(data, mesh, subMeshes) {
	        var readData = new Laya.Byte(data);
	        readData.pos = 0;
	        var version = readData.readUTFString();
	        switch (version) {
	            case "LAYAMODEL:0301":
	            case "LAYAMODEL:0400":
	            case "LAYAMODEL:0401":
	                LoadModelV04.parse(readData, version, mesh, subMeshes);
	                break;
	            case "LAYAMODEL:05":
	            case "LAYAMODEL:COMPRESSION_05":
	                LoadModelV05.parse(readData, version, mesh, subMeshes);
	                break;
	            default:
	                throw new Error("MeshReader: unknown mesh version.");
	        }
	        mesh._setSubMeshes(subMeshes);
	    }
	}

	class Mesh extends Laya.Resource {
	    constructor(isReadable = true) {
	        super();
	        this._tempVector30 = new Vector3();
	        this._tempVector31 = new Vector3();
	        this._tempVector32 = new Vector3();
	        this._minVerticesUpdate = -1;
	        this._maxVerticesUpdate = -1;
	        this._needUpdateBounds = true;
	        this._bounds = new Bounds(new Vector3(), new Vector3());
	        this._bufferState = new BufferState();
	        this._instanceBufferState = new BufferState();
	        this._vertexBuffer = null;
	        this._indexBuffer = null;
	        this._vertexCount = 0;
	        this._isReadable = isReadable;
	        this._subMeshes = [];
	        this._skinDataPathMarks = [];
	    }
	    static __init__() {
	        var physics3D = Physics3D._physics3D;
	        if (physics3D) {
	            Mesh._nativeTempVector30 = new physics3D.btVector3(0, 0, 0);
	            Mesh._nativeTempVector31 = new physics3D.btVector3(0, 0, 0);
	            Mesh._nativeTempVector32 = new physics3D.btVector3(0, 0, 0);
	        }
	    }
	    static _parse(data, propertyParams = null, constructParams = null) {
	        var mesh = new Mesh();
	        MeshReader.read(data, mesh, mesh._subMeshes);
	        return mesh;
	    }
	    static load(url, complete) {
	        Laya.ILaya.loader.create(url, complete, null, Mesh.MESH);
	    }
	    get inverseAbsoluteBindPoses() {
	        return this._inverseBindPoses;
	    }
	    get vertexCount() {
	        return this._vertexCount;
	    }
	    get indexCount() {
	        return this._indexBuffer.indexCount;
	    }
	    get subMeshCount() {
	        return this._subMeshes.length;
	    }
	    get bounds() {
	        return this._bounds;
	    }
	    set bounds(value) {
	        if (this._bounds !== value)
	            value.cloneTo(this._bounds);
	    }
	    _getPositionElement(vertexBuffer) {
	        var vertexElements = vertexBuffer.vertexDeclaration._vertexElements;
	        for (var i = 0, n = vertexElements.length; i < n; i++) {
	            var vertexElement = vertexElements[i];
	            if (vertexElement._elementFormat === VertexElementFormat.Vector3 && vertexElement._elementUsage === VertexMesh.MESH_POSITION0)
	                return vertexElement;
	        }
	        return null;
	    }
	    _getVerticeElementData(data, elementUsage) {
	        data.length = this._vertexCount;
	        var verDec = this._vertexBuffer.vertexDeclaration;
	        var element = verDec.getVertexElementByUsage(elementUsage);
	        if (element) {
	            var uint8Vertices = this._vertexBuffer.getUint8Data();
	            var floatVertices = this._vertexBuffer.getFloat32Data();
	            var uint8VerStr = verDec.vertexStride;
	            var floatVerStr = uint8VerStr / 4;
	            var uint8EleOffset = element._offset;
	            var floatEleOffset = uint8EleOffset / 4;
	            switch (elementUsage) {
	                case VertexMesh.MESH_TEXTURECOORDINATE0:
	                case VertexMesh.MESH_TEXTURECOORDINATE1:
	                    for (var i = 0; i < this._vertexCount; i++) {
	                        var offset = floatVerStr * i + floatEleOffset;
	                        data[i] = new Vector2(floatVertices[offset], floatVertices[offset + 1]);
	                    }
	                    break;
	                case VertexMesh.MESH_POSITION0:
	                case VertexMesh.MESH_NORMAL0:
	                    for (var i = 0; i < this._vertexCount; i++) {
	                        var offset = floatVerStr * i + floatEleOffset;
	                        data[i] = new Vector3(floatVertices[offset], floatVertices[offset + 1], floatVertices[offset + 2]);
	                    }
	                    break;
	                case VertexMesh.MESH_TANGENT0:
	                case VertexMesh.MESH_BLENDWEIGHT0:
	                    for (var i = 0; i < this._vertexCount; i++) {
	                        var offset = floatVerStr * i + floatEleOffset;
	                        data[i] = new Vector4(floatVertices[offset], floatVertices[offset + 1], floatVertices[offset + 2], floatVertices[offset + 3]);
	                    }
	                    break;
	                case VertexMesh.MESH_COLOR0:
	                    for (var i = 0; i < this._vertexCount; i++) {
	                        var offset = floatVerStr * i + floatEleOffset;
	                        data[i] = new Color(floatVertices[offset], floatVertices[offset + 1], floatVertices[offset + 2], floatVertices[offset + 3]);
	                    }
	                    break;
	                case VertexMesh.MESH_BLENDINDICES0:
	                    for (var i = 0; i < this._vertexCount; i++) {
	                        var offset = uint8VerStr * i + uint8EleOffset;
	                        data[i] = new Vector4(uint8Vertices[offset], uint8Vertices[offset + 1], uint8Vertices[offset + 2], uint8Vertices[offset + 3]);
	                    }
	                    break;
	                default:
	                    throw "Mesh:Unknown elementUsage.";
	            }
	        }
	    }
	    _setVerticeElementData(data, elementUsage) {
	        var verDec = this._vertexBuffer.vertexDeclaration;
	        var element = verDec.getVertexElementByUsage(elementUsage);
	        if (element) {
	            var uint8Vertices = this._vertexBuffer.getUint8Data();
	            var floatVertices = this._vertexBuffer.getFloat32Data();
	            var uint8VerStr = verDec.vertexStride;
	            var float8VerStr = uint8VerStr / 4;
	            var uint8EleOffset = element._offset;
	            var floatEleOffset = uint8EleOffset / 4;
	            switch (elementUsage) {
	                case VertexMesh.MESH_TEXTURECOORDINATE0:
	                case VertexMesh.MESH_TEXTURECOORDINATE1:
	                    for (var i = 0, n = data.length; i < n; i++) {
	                        var offset = float8VerStr * i + floatEleOffset;
	                        var vec2 = data[i];
	                        floatVertices[offset] = vec2.x;
	                        floatVertices[offset + 1] = vec2.y;
	                    }
	                    break;
	                case VertexMesh.MESH_POSITION0:
	                case VertexMesh.MESH_NORMAL0:
	                    for (var i = 0, n = data.length; i < n; i++) {
	                        var offset = float8VerStr * i + floatEleOffset;
	                        var vec3 = data[i];
	                        floatVertices[offset] = vec3.x;
	                        floatVertices[offset + 1] = vec3.y;
	                        floatVertices[offset + 2] = vec3.z;
	                    }
	                    break;
	                case VertexMesh.MESH_TANGENT0:
	                case VertexMesh.MESH_BLENDWEIGHT0:
	                    for (var i = 0, n = data.length; i < n; i++) {
	                        var offset = float8VerStr * i + floatEleOffset;
	                        var vec4 = data[i];
	                        floatVertices[offset] = vec4.x;
	                        floatVertices[offset + 1] = vec4.y;
	                        floatVertices[offset + 2] = vec4.z;
	                        floatVertices[offset + 3] = vec4.w;
	                    }
	                    break;
	                case VertexMesh.MESH_COLOR0:
	                    for (var i = 0, n = data.length; i < n; i++) {
	                        var offset = float8VerStr * i + floatEleOffset;
	                        var cor = data[i];
	                        floatVertices[offset] = cor.r;
	                        floatVertices[offset + 1] = cor.g;
	                        floatVertices[offset + 2] = cor.b;
	                        floatVertices[offset + 2] = cor.a;
	                    }
	                    break;
	                case VertexMesh.MESH_BLENDINDICES0:
	                    for (var i = 0, n = data.length; i < n; i++) {
	                        var offset = uint8VerStr * i + uint8EleOffset;
	                        var vec4 = data[i];
	                        uint8Vertices[offset] = vec4.x;
	                        uint8Vertices[offset + 1] = vec4.y;
	                        uint8Vertices[offset + 2] = vec4.z;
	                        uint8Vertices[offset + 3] = vec4.w;
	                    }
	                    break;
	                default:
	                    throw "Mesh:Unknown elementUsage.";
	            }
	            this._minVerticesUpdate = 0;
	            this._maxVerticesUpdate = Number.MAX_SAFE_INTEGER;
	        }
	        else {
	            console.warn("Mesh: the mesh don't have  this VertexElement.");
	        }
	    }
	    _disposeResource() {
	        for (var i = 0, n = this._subMeshes.length; i < n; i++)
	            this._subMeshes[i].destroy();
	        this._nativeTriangleMesh && window.Physics3D.destroy(this._nativeTriangleMesh);
	        this._vertexBuffer.destroy();
	        this._indexBuffer.destroy();
	        this._setCPUMemory(0);
	        this._setGPUMemory(0);
	        this._bufferState.destroy();
	        this._instanceBufferState.destroy();
	        this._bufferState = null;
	        this._instanceBufferState = null;
	        this._vertexBuffer = null;
	        this._indexBuffer = null;
	        this._subMeshes = null;
	        this._nativeTriangleMesh = null;
	        this._indexBuffer = null;
	        this._boneNames = null;
	        this._inverseBindPoses = null;
	    }
	    _setSubMeshes(subMeshes) {
	        this._subMeshes = subMeshes;
	        for (var i = 0, n = subMeshes.length; i < n; i++)
	            subMeshes[i]._indexInMesh = i;
	        this.calculateBounds();
	    }
	    _setBuffer(vertexBuffer, indexBuffer) {
	        var bufferState = this._bufferState;
	        bufferState.bind();
	        bufferState.applyVertexBuffer(vertexBuffer);
	        bufferState.applyIndexBuffer(indexBuffer);
	        bufferState.unBind();
	        var instanceBufferState = this._instanceBufferState;
	        instanceBufferState.bind();
	        instanceBufferState.applyVertexBuffer(vertexBuffer);
	        instanceBufferState.applyInstanceVertexBuffer(SubMeshInstanceBatch.instance.instanceWorldMatrixBuffer);
	        instanceBufferState.applyInstanceVertexBuffer(SubMeshInstanceBatch.instance.instanceMVPMatrixBuffer);
	        instanceBufferState.applyIndexBuffer(indexBuffer);
	        instanceBufferState.unBind();
	    }
	    _getPhysicMesh() {
	        if (!this._nativeTriangleMesh) {
	            var physics3D = window.Physics3D;
	            var triangleMesh = new physics3D.btTriangleMesh();
	            var nativePositio0 = Mesh._nativeTempVector30;
	            var nativePositio1 = Mesh._nativeTempVector31;
	            var nativePositio2 = Mesh._nativeTempVector32;
	            var position0 = this._tempVector30;
	            var position1 = this._tempVector31;
	            var position2 = this._tempVector32;
	            var vertexBuffer = this._vertexBuffer;
	            var positionElement = this._getPositionElement(vertexBuffer);
	            var verticesData = vertexBuffer.getFloat32Data();
	            var floatCount = vertexBuffer.vertexDeclaration.vertexStride / 4;
	            var posOffset = positionElement._offset / 4;
	            var indices = this._indexBuffer.getData();
	            for (var i = 0, n = indices.length; i < n; i += 3) {
	                var p0Index = indices[i] * floatCount + posOffset;
	                var p1Index = indices[i + 1] * floatCount + posOffset;
	                var p2Index = indices[i + 2] * floatCount + posOffset;
	                position0.setValue(verticesData[p0Index], verticesData[p0Index + 1], verticesData[p0Index + 2]);
	                position1.setValue(verticesData[p1Index], verticesData[p1Index + 1], verticesData[p1Index + 2]);
	                position2.setValue(verticesData[p2Index], verticesData[p2Index + 1], verticesData[p2Index + 2]);
	                Utils3D._convertToBulletVec3(position0, nativePositio0, true);
	                Utils3D._convertToBulletVec3(position1, nativePositio1, true);
	                Utils3D._convertToBulletVec3(position2, nativePositio2, true);
	                triangleMesh.addTriangle(nativePositio0, nativePositio1, nativePositio2, true);
	            }
	            this._nativeTriangleMesh = triangleMesh;
	        }
	        return this._nativeTriangleMesh;
	    }
	    _uploadVerticesData() {
	        var min = this._minVerticesUpdate;
	        var max = this._maxVerticesUpdate;
	        if (min !== -1 && max !== -1) {
	            var offset = min;
	            this._vertexBuffer.setData(this._vertexBuffer.getUint8Data().buffer, offset, offset, max - min);
	            this._minVerticesUpdate = -1;
	            this._maxVerticesUpdate = -1;
	        }
	    }
	    getSubMesh(index) {
	        return this._subMeshes[index];
	    }
	    getPositions(positions) {
	        if (this._isReadable)
	            this._getVerticeElementData(positions, VertexMesh.MESH_POSITION0);
	        else
	            throw "Mesh:can't get positions on mesh,isReadable must be true.";
	    }
	    setPositions(positions) {
	        if (this._isReadable) {
	            this._setVerticeElementData(positions, VertexMesh.MESH_POSITION0);
	            this._needUpdateBounds = true;
	        }
	        else {
	            throw "Mesh:setPosition() need isReadable must be true or use setVertices().";
	        }
	    }
	    getColors(colors) {
	        if (this._isReadable)
	            this._getVerticeElementData(colors, VertexMesh.MESH_COLOR0);
	        else
	            throw "Mesh:can't get colors on mesh,isReadable must be true.";
	    }
	    setColors(colors) {
	        if (this._isReadable)
	            this._setVerticeElementData(colors, VertexMesh.MESH_COLOR0);
	        else
	            throw "Mesh:setColors() need isReadable must be true or use setVertices().";
	    }
	    getUVs(uvs, channel = 0) {
	        if (this._isReadable) {
	            switch (channel) {
	                case 0:
	                    this._getVerticeElementData(uvs, VertexMesh.MESH_TEXTURECOORDINATE0);
	                    break;
	                case 1:
	                    this._getVerticeElementData(uvs, VertexMesh.MESH_TEXTURECOORDINATE1);
	                    break;
	                default:
	                    throw "Mesh:Invalid channel.";
	            }
	        }
	        else {
	            throw "Mesh:can't get uvs on mesh,isReadable must be true.";
	        }
	    }
	    setUVs(uvs, channel = 0) {
	        if (this._isReadable) {
	            switch (channel) {
	                case 0:
	                    this._setVerticeElementData(uvs, VertexMesh.MESH_TEXTURECOORDINATE0);
	                    break;
	                case 1:
	                    this._setVerticeElementData(uvs, VertexMesh.MESH_TEXTURECOORDINATE1);
	                    break;
	                default:
	                    throw "Mesh:Invalid channel.";
	            }
	        }
	        else {
	            throw "Mesh:setUVs() need isReadable must be true or use setVertices().";
	        }
	    }
	    getNormals(normals) {
	        if (this._isReadable)
	            this._getVerticeElementData(normals, VertexMesh.MESH_NORMAL0);
	        else
	            throw "Mesh:can't get colors on mesh,isReadable must be true.";
	    }
	    setNormals(normals) {
	        if (this._isReadable)
	            this._setVerticeElementData(normals, VertexMesh.MESH_NORMAL0);
	        else
	            throw "Mesh:setNormals() need must be true or use setVertices().";
	    }
	    getTangents(tangents) {
	        if (this._isReadable)
	            this._getVerticeElementData(tangents, VertexMesh.MESH_TANGENT0);
	        else
	            throw "Mesh:can't get colors on mesh,isReadable must be true.";
	    }
	    setTangents(tangents) {
	        if (this._isReadable)
	            this._setVerticeElementData(tangents, VertexMesh.MESH_TANGENT0);
	        else
	            throw "Mesh:setTangents() need isReadable must be true or use setVertices().";
	    }
	    getBoneWeights(boneWeights) {
	        if (this._isReadable)
	            this._getVerticeElementData(boneWeights, VertexMesh.MESH_BLENDWEIGHT0);
	        else
	            throw "Mesh:can't get boneWeights on mesh,isReadable must be true.";
	    }
	    setBoneWeights(boneWeights) {
	        if (this._isReadable)
	            this._setVerticeElementData(boneWeights, VertexMesh.MESH_BLENDWEIGHT0);
	        else
	            throw "Mesh:setBoneWeights() need isReadable must be true or use setVertices().";
	    }
	    getBoneIndices(boneIndices) {
	        if (this._isReadable)
	            this._getVerticeElementData(boneIndices, VertexMesh.MESH_BLENDINDICES0);
	        else
	            throw "Mesh:can't get boneIndices on mesh,isReadable must be true.";
	    }
	    setBoneIndices(boneIndices) {
	        if (this._isReadable)
	            this._setVerticeElementData(boneIndices, VertexMesh.MESH_BLENDINDICES0);
	        else
	            throw "Mesh:setBoneIndices() need isReadable must be true or use setVertices().";
	    }
	    markAsUnreadbale() {
	        this._uploadVerticesData();
	        this._vertexBuffer.markAsUnreadbale();
	        this._isReadable = false;
	    }
	    getVertexDeclaration() {
	        return this._vertexBuffer._vertexDeclaration;
	    }
	    getVertices() {
	        if (this._isReadable)
	            return this._vertexBuffer.getUint8Data().buffer.slice(0);
	        else
	            throw "Mesh:can't get vertices on mesh,isReadable must be true.";
	    }
	    setVertices(vertices) {
	        this._vertexBuffer.setData(vertices);
	        this._needUpdateBounds = true;
	    }
	    getIndices() {
	        if (this._isReadable)
	            return this._indexBuffer.getData().slice();
	        else
	            throw "Mesh:can't get indices on subMesh,mesh's isReadable must be true.";
	    }
	    setIndices(indices) {
	        this._indexBuffer.setData(indices);
	    }
	    calculateBounds() {
	        if (this._isReadable) {
	            if (this._needUpdateBounds) {
	                var min = this._tempVector30;
	                var max = this._tempVector31;
	                min.x = min.y = min.z = Number.MAX_VALUE;
	                max.x = max.y = max.z = -Number.MAX_VALUE;
	                var vertexBuffer = this._vertexBuffer;
	                var positionElement = this._getPositionElement(vertexBuffer);
	                var verticesData = vertexBuffer.getFloat32Data();
	                var floatCount = vertexBuffer.vertexDeclaration.vertexStride / 4;
	                var posOffset = positionElement._offset / 4;
	                for (var j = 0, m = verticesData.length; j < m; j += floatCount) {
	                    var ofset = j + posOffset;
	                    var pX = verticesData[ofset];
	                    var pY = verticesData[ofset + 1];
	                    var pZ = verticesData[ofset + 2];
	                    min.x = Math.min(min.x, pX);
	                    min.y = Math.min(min.y, pY);
	                    min.z = Math.min(min.z, pZ);
	                    max.x = Math.max(max.x, pX);
	                    max.y = Math.max(max.y, pY);
	                    max.z = Math.max(max.z, pZ);
	                }
	                this._bounds.setMin(min);
	                this._bounds.setMax(max);
	                this._needUpdateBounds = false;
	            }
	        }
	        else {
	            throw "Mesh:can't calculate bounds on subMesh,mesh's isReadable must be true.";
	        }
	    }
	    cloneTo(destObject) {
	        var destMesh = destObject;
	        var vb = this._vertexBuffer;
	        var destVB = new VertexBuffer3D(vb._byteLength, vb.bufferUsage, vb.canRead);
	        destVB.vertexDeclaration = vb.vertexDeclaration;
	        destVB.setData(vb.getUint8Data().slice().buffer);
	        destMesh._vertexBuffer = destVB;
	        destMesh._vertexCount = this._vertexCount;
	        var ib = this._indexBuffer;
	        var destIB = new IndexBuffer3D(IndexBuffer3D.INDEXTYPE_USHORT, ib.indexCount, ib.bufferUsage, ib.canRead);
	        destIB.setData(ib.getData().slice());
	        destMesh._indexBuffer = destIB;
	        destMesh._setBuffer(destMesh._vertexBuffer, destIB);
	        destMesh._setCPUMemory(this.cpuMemory);
	        destMesh._setGPUMemory(this.gpuMemory);
	        var i;
	        var boneNames = this._boneNames;
	        var destBoneNames = destMesh._boneNames = [];
	        for (i = 0; i < boneNames.length; i++)
	            destBoneNames[i] = boneNames[i];
	        var inverseBindPoses = this._inverseBindPoses;
	        var destInverseBindPoses = destMesh._inverseBindPoses = [];
	        for (i = 0; i < inverseBindPoses.length; i++)
	            destInverseBindPoses[i] = inverseBindPoses[i];
	        destMesh._bindPoseIndices = new Uint16Array(this._bindPoseIndices);
	        for (i = 0; i < this._skinDataPathMarks.length; i++)
	            destMesh._skinDataPathMarks[i] = this._skinDataPathMarks[i].slice();
	        for (i = 0; i < this.subMeshCount; i++) {
	            var subMesh = this._subMeshes[i];
	            var subIndexBufferStart = subMesh._subIndexBufferStart;
	            var subIndexBufferCount = subMesh._subIndexBufferCount;
	            var boneIndicesList = subMesh._boneIndicesList;
	            var destSubmesh = new SubMesh(destMesh);
	            destSubmesh._subIndexBufferStart.length = subIndexBufferStart.length;
	            destSubmesh._subIndexBufferCount.length = subIndexBufferCount.length;
	            destSubmesh._boneIndicesList.length = boneIndicesList.length;
	            for (var j = 0; j < subIndexBufferStart.length; j++)
	                destSubmesh._subIndexBufferStart[j] = subIndexBufferStart[j];
	            for (j = 0; j < subIndexBufferCount.length; j++)
	                destSubmesh._subIndexBufferCount[j] = subIndexBufferCount[j];
	            for (j = 0; j < boneIndicesList.length; j++)
	                destSubmesh._boneIndicesList[j] = new Uint16Array(boneIndicesList[j]);
	            destSubmesh._indexBuffer = destIB;
	            destSubmesh._indexStart = subMesh._indexStart;
	            destSubmesh._indexCount = subMesh._indexCount;
	            destSubmesh._indices = new Uint16Array(destIB.getData().buffer, subMesh._indexStart * 2, subMesh._indexCount);
	            var vertexBuffer = destMesh._vertexBuffer;
	            destSubmesh._vertexBuffer = vertexBuffer;
	            destMesh._subMeshes.push(destSubmesh);
	        }
	        destMesh._setSubMeshes(destMesh._subMeshes);
	    }
	    clone() {
	        var dest = new Mesh();
	        this.cloneTo(dest);
	        return dest;
	    }
	}
	Mesh.MESH = "MESH";

	class PrimitiveMesh {
	    static __init__() {
	    }
	    static _createMesh(vertexDeclaration, vertices, indices) {
	        var gl = Laya.LayaGL.instance;
	        var mesh = new Mesh();
	        var subMesh = new SubMesh(mesh);
	        var vertexBuffer = new VertexBuffer3D(vertices.length * 4, gl.STATIC_DRAW, true);
	        vertexBuffer.vertexDeclaration = vertexDeclaration;
	        vertexBuffer.setData(vertices.buffer);
	        mesh._vertexBuffer = vertexBuffer;
	        mesh._vertexCount = vertexBuffer._byteLength / vertexDeclaration.vertexStride;
	        var indexBuffer = new IndexBuffer3D(IndexBuffer3D.INDEXTYPE_USHORT, indices.length, gl.STATIC_DRAW, true);
	        indexBuffer.setData(indices);
	        mesh._indexBuffer = indexBuffer;
	        mesh._setBuffer(vertexBuffer, indexBuffer);
	        subMesh._vertexBuffer = vertexBuffer;
	        subMesh._indexBuffer = indexBuffer;
	        subMesh._setIndexRange(0, indexBuffer.indexCount);
	        var subIndexBufferStart = subMesh._subIndexBufferStart;
	        var subIndexBufferCount = subMesh._subIndexBufferCount;
	        var boneIndicesList = subMesh._boneIndicesList;
	        subIndexBufferStart.length = 1;
	        subIndexBufferCount.length = 1;
	        boneIndicesList.length = 1;
	        subIndexBufferStart[0] = 0;
	        subIndexBufferCount[0] = indexBuffer.indexCount;
	        var subMeshes = [];
	        subMeshes.push(subMesh);
	        mesh._setSubMeshes(subMeshes);
	        var memorySize = vertexBuffer._byteLength + indexBuffer._byteLength;
	        mesh._setCPUMemory(memorySize);
	        mesh._setGPUMemory(memorySize);
	        return mesh;
	    }
	    static createBox(long = 1, height = 1, width = 1) {
	        var vertexDeclaration = VertexMesh.getVertexDeclaration("POSITION,NORMAL,UV");
	        var halfLong = long / 2;
	        var halfHeight = height / 2;
	        var halfWidth = width / 2;
	        var vertices = new Float32Array([
	            -halfLong, halfHeight, -halfWidth, 0, 1, 0, 0, 0, halfLong, halfHeight, -halfWidth, 0, 1, 0, 1, 0, halfLong, halfHeight, halfWidth, 0, 1, 0, 1, 1, -halfLong, halfHeight, halfWidth, 0, 1, 0, 0, 1,
	            -halfLong, -halfHeight, -halfWidth, 0, -1, 0, 0, 1, halfLong, -halfHeight, -halfWidth, 0, -1, 0, 1, 1, halfLong, -halfHeight, halfWidth, 0, -1, 0, 1, 0, -halfLong, -halfHeight, halfWidth, 0, -1, 0, 0, 0,
	            -halfLong, halfHeight, -halfWidth, -1, 0, 0, 0, 0, -halfLong, halfHeight, halfWidth, -1, 0, 0, 1, 0, -halfLong, -halfHeight, halfWidth, -1, 0, 0, 1, 1, -halfLong, -halfHeight, -halfWidth, -1, 0, 0, 0, 1,
	            halfLong, halfHeight, -halfWidth, 1, 0, 0, 1, 0, halfLong, halfHeight, halfWidth, 1, 0, 0, 0, 0, halfLong, -halfHeight, halfWidth, 1, 0, 0, 0, 1, halfLong, -halfHeight, -halfWidth, 1, 0, 0, 1, 1,
	            -halfLong, halfHeight, halfWidth, 0, 0, 1, 0, 0, halfLong, halfHeight, halfWidth, 0, 0, 1, 1, 0, halfLong, -halfHeight, halfWidth, 0, 0, 1, 1, 1, -halfLong, -halfHeight, halfWidth, 0, 0, 1, 0, 1,
	            -halfLong, halfHeight, -halfWidth, 0, 0, -1, 1, 0, halfLong, halfHeight, -halfWidth, 0, 0, -1, 0, 0, halfLong, -halfHeight, -halfWidth, 0, 0, -1, 0, 1, -halfLong, -halfHeight, -halfWidth, 0, 0, -1, 1, 1
	        ]);
	        var indices = new Uint16Array([
	            0, 1, 2, 2, 3, 0,
	            4, 7, 6, 6, 5, 4,
	            8, 9, 10, 10, 11, 8,
	            12, 15, 14, 14, 13, 12,
	            16, 17, 18, 18, 19, 16,
	            20, 23, 22, 22, 21, 20
	        ]);
	        return PrimitiveMesh._createMesh(vertexDeclaration, vertices, indices);
	    }
	    static createCapsule(radius = 0.5, height = 2, stacks = 16, slices = 32) {
	        var vertexCount = (stacks + 1) * (slices + 1) * 2 + (slices + 1) * 2;
	        var indexCount = (3 * stacks * (slices + 1)) * 2 * 2 + 2 * slices * 3;
	        var vertexDeclaration = VertexMesh.getVertexDeclaration("POSITION,NORMAL,UV");
	        var vertexFloatStride = vertexDeclaration.vertexStride / 4;
	        var vertices = new Float32Array(vertexCount * vertexFloatStride);
	        var indices = new Uint16Array(indexCount);
	        var stackAngle = (Math.PI / 2.0) / stacks;
	        var sliceAngle = (Math.PI * 2.0) / slices;
	        var hcHeight = height / 2 - radius;
	        var posX = 0;
	        var posY = 0;
	        var posZ = 0;
	        var vc = 0;
	        var ic = 0;
	        var verticeCount = 0;
	        var stack, slice;
	        for (stack = 0; stack <= stacks; stack++) {
	            for (slice = 0; slice <= slices; slice++) {
	                posX = radius * Math.cos(stack * stackAngle) * Math.cos(slice * sliceAngle + Math.PI);
	                posY = radius * Math.sin(stack * stackAngle);
	                posZ = radius * Math.cos(stack * stackAngle) * Math.sin(slice * sliceAngle + Math.PI);
	                vertices[vc++] = posX;
	                vertices[vc++] = posY + hcHeight;
	                vertices[vc++] = posZ;
	                vertices[vc++] = posX;
	                vertices[vc++] = posY;
	                vertices[vc++] = posZ;
	                vertices[vc++] = 1 - slice / slices;
	                vertices[vc++] = (1 - stack / stacks) * ((Math.PI * radius / 2) / (height + Math.PI * radius));
	                if (stack < stacks) {
	                    indices[ic++] = (stack * (slices + 1)) + slice + (slices + 1);
	                    indices[ic++] = (stack * (slices + 1)) + slice;
	                    indices[ic++] = (stack * (slices + 1)) + slice + 1;
	                    indices[ic++] = (stack * (slices + 1)) + slice + (slices);
	                    indices[ic++] = (stack * (slices + 1)) + slice;
	                    indices[ic++] = (stack * (slices + 1)) + slice + (slices + 1);
	                }
	            }
	        }
	        verticeCount += (stacks + 1) * (slices + 1);
	        for (stack = 0; stack <= stacks; stack++) {
	            for (slice = 0; slice <= slices; slice++) {
	                posX = radius * Math.cos(stack * stackAngle) * Math.cos(slice * sliceAngle + Math.PI);
	                posY = radius * Math.sin(-stack * stackAngle);
	                posZ = radius * Math.cos(stack * stackAngle) * Math.sin(slice * sliceAngle + Math.PI);
	                vertices[vc++] = posX;
	                vertices[vc++] = posY - hcHeight;
	                vertices[vc++] = posZ;
	                vertices[vc++] = posX;
	                vertices[vc++] = posY;
	                vertices[vc++] = posZ;
	                vertices[vc++] = 1 - slice / slices;
	                vertices[vc++] = ((stack / stacks) * (Math.PI * radius / 2) + (height + Math.PI * radius / 2)) / (height + Math.PI * radius);
	                if (stack < stacks) {
	                    indices[ic++] = verticeCount + (stack * (slices + 1)) + slice;
	                    indices[ic++] = verticeCount + (stack * (slices + 1)) + slice + (slices + 1);
	                    indices[ic++] = verticeCount + (stack * (slices + 1)) + slice + 1;
	                    indices[ic++] = verticeCount + (stack * (slices + 1)) + slice;
	                    indices[ic++] = verticeCount + (stack * (slices + 1)) + slice + (slices);
	                    indices[ic++] = verticeCount + (stack * (slices + 1)) + slice + (slices + 1);
	                }
	            }
	        }
	        verticeCount += (stacks + 1) * (slices + 1);
	        for (slice = 0; slice <= slices; slice++) {
	            posX = radius * Math.cos(slice * sliceAngle + Math.PI);
	            posY = hcHeight;
	            posZ = radius * Math.sin(slice * sliceAngle + Math.PI);
	            vertices[vc++] = posX;
	            vertices[vc + (slices + 1) * 8 - 1] = posX;
	            vertices[vc++] = posY;
	            vertices[vc + (slices + 1) * 8 - 1] = -posY;
	            vertices[vc++] = posZ;
	            vertices[vc + (slices + 1) * 8 - 1] = posZ;
	            vertices[vc++] = posX;
	            vertices[vc + (slices + 1) * 8 - 1] = posX;
	            vertices[vc++] = 0;
	            vertices[vc + (slices + 1) * 8 - 1] = 0;
	            vertices[vc++] = posZ;
	            vertices[vc + (slices + 1) * 8 - 1] = posZ;
	            vertices[vc++] = 1 - slice * 1 / slices;
	            vertices[vc + (slices + 1) * 8 - 1] = 1 - slice * 1 / slices;
	            vertices[vc++] = (Math.PI * radius / 2) / (height + Math.PI * radius);
	            vertices[vc + (slices + 1) * 8 - 1] = (Math.PI * radius / 2 + height) / (height + Math.PI * radius);
	        }
	        for (slice = 0; slice < slices; slice++) {
	            indices[ic++] = slice + verticeCount + (slices + 1);
	            indices[ic++] = slice + verticeCount + 1;
	            indices[ic++] = slice + verticeCount;
	            indices[ic++] = slice + verticeCount + (slices + 1);
	            indices[ic++] = slice + verticeCount + (slices + 1) + 1;
	            indices[ic++] = slice + verticeCount + 1;
	        }
	        verticeCount += 2 * (slices + 1);
	        return PrimitiveMesh._createMesh(vertexDeclaration, vertices, indices);
	    }
	    static createCone(radius = 0.5, height = 1, slices = 32) {
	        var vertexCount = (slices + 1 + 1) + (slices + 1) * 2;
	        var indexCount = 6 * slices + 3 * slices;
	        var vertexDeclaration = VertexMesh.getVertexDeclaration("POSITION,NORMAL,UV");
	        var vertexFloatStride = vertexDeclaration.vertexStride / 4;
	        var vertices = new Float32Array(vertexCount * vertexFloatStride);
	        var indices = new Uint16Array(indexCount);
	        var sliceAngle = (Math.PI * 2.0) / slices;
	        var halfHeight = height / 2;
	        var curAngle = 0;
	        var verticeCount = 0;
	        var posX = 0;
	        var posY = 0;
	        var posZ = 0;
	        var normal = new Vector3();
	        var downV3 = new Vector3(0, -1, 0);
	        var upPoint = new Vector3(0, halfHeight, 0);
	        var downPoint = new Vector3();
	        var v3 = new Vector3();
	        var q4 = new Quaternion();
	        var rotateAxis = new Vector3();
	        var rotateRadius;
	        var vc = 0;
	        var ic = 0;
	        for (var rv = 0; rv <= slices; rv++) {
	            curAngle = rv * sliceAngle;
	            posX = Math.cos(curAngle + Math.PI) * radius;
	            posY = halfHeight;
	            posZ = Math.sin(curAngle + Math.PI) * radius;
	            vertices[vc++] = 0;
	            vertices[vc + (slices + 1) * 8 - 1] = posX;
	            vertices[vc++] = posY;
	            vertices[vc + (slices + 1) * 8 - 1] = -posY;
	            vertices[vc++] = 0;
	            vertices[vc + (slices + 1) * 8 - 1] = posZ;
	            normal.x = posX;
	            normal.y = 0;
	            normal.z = posZ;
	            downPoint.x = posX;
	            downPoint.y = -posY;
	            downPoint.z = posZ;
	            Vector3.subtract(downPoint, upPoint, v3);
	            Vector3.normalize(v3, v3);
	            rotateRadius = Math.acos(Vector3.dot(downV3, v3));
	            Vector3.cross(downV3, v3, rotateAxis);
	            Vector3.normalize(rotateAxis, rotateAxis);
	            Quaternion.createFromAxisAngle(rotateAxis, rotateRadius, q4);
	            Vector3.normalize(normal, normal);
	            Vector3.transformQuat(normal, q4, normal);
	            Vector3.normalize(normal, normal);
	            vertices[vc++] = normal.x;
	            vertices[vc + (slices + 1) * 8 - 1] = normal.x;
	            vertices[vc++] = normal.y;
	            vertices[vc + (slices + 1) * 8 - 1] = normal.y;
	            vertices[vc++] = normal.z;
	            vertices[vc + (slices + 1) * 8 - 1] = normal.z;
	            vertices[vc++] = 1 - rv * 1 / slices;
	            vertices[vc + (slices + 1) * 8 - 1] = 1 - rv * 1 / slices;
	            vertices[vc++] = 0;
	            vertices[vc + (slices + 1) * 8 - 1] = 1;
	        }
	        vc += (slices + 1) * 8;
	        for (var ri = 0; ri < slices; ri++) {
	            indices[ic++] = ri + verticeCount + (slices + 1);
	            indices[ic++] = ri + verticeCount + 1;
	            indices[ic++] = ri + verticeCount;
	            indices[ic++] = ri + verticeCount + (slices + 1);
	            indices[ic++] = ri + verticeCount + (slices + 1) + 1;
	            indices[ic++] = ri + verticeCount + 1;
	        }
	        verticeCount += 2 * (slices + 1);
	        for (var bv = 0; bv <= slices; bv++) {
	            if (bv === 0) {
	                vertices[vc++] = 0;
	                vertices[vc++] = -halfHeight;
	                vertices[vc++] = 0;
	                vertices[vc++] = 0;
	                vertices[vc++] = -1;
	                vertices[vc++] = 0;
	                vertices[vc++] = 0.5;
	                vertices[vc++] = 0.5;
	            }
	            curAngle = bv * sliceAngle;
	            posX = Math.cos(curAngle + Math.PI) * radius;
	            posY = -halfHeight;
	            posZ = Math.sin(curAngle + Math.PI) * radius;
	            vertices[vc++] = posX;
	            vertices[vc++] = posY;
	            vertices[vc++] = posZ;
	            vertices[vc++] = 0;
	            vertices[vc++] = -1;
	            vertices[vc++] = 0;
	            vertices[vc++] = 0.5 + Math.cos(curAngle) * 0.5;
	            vertices[vc++] = 0.5 + Math.sin(curAngle) * 0.5;
	        }
	        for (var bi = 0; bi < slices; bi++) {
	            indices[ic++] = 0 + verticeCount;
	            indices[ic++] = bi + 2 + verticeCount;
	            indices[ic++] = bi + 1 + verticeCount;
	        }
	        verticeCount += slices + 1 + 1;
	        return PrimitiveMesh._createMesh(vertexDeclaration, vertices, indices);
	    }
	    static createCylinder(radius = 0.5, height = 2, slices = 32) {
	        var vertexCount = (slices + 1 + 1) + (slices + 1) * 2 + (slices + 1 + 1);
	        var indexCount = 3 * slices + 6 * slices + 3 * slices;
	        var vertexDeclaration = VertexMesh.getVertexDeclaration("POSITION,NORMAL,UV");
	        var vertexFloatStride = vertexDeclaration.vertexStride / 4;
	        var vertices = new Float32Array(vertexCount * vertexFloatStride);
	        var indices = new Uint16Array(indexCount);
	        var sliceAngle = (Math.PI * 2.0) / slices;
	        var halfHeight = height / 2;
	        var curAngle = 0;
	        var verticeCount = 0;
	        var posX = 0;
	        var posY = 0;
	        var posZ = 0;
	        var vc = 0;
	        var ic = 0;
	        for (var tv = 0; tv <= slices; tv++) {
	            if (tv === 0) {
	                vertices[vc++] = 0;
	                vertices[vc++] = halfHeight;
	                vertices[vc++] = 0;
	                vertices[vc++] = 0;
	                vertices[vc++] = 1;
	                vertices[vc++] = 0;
	                vertices[vc++] = 0.5;
	                vertices[vc++] = 0.5;
	            }
	            curAngle = tv * sliceAngle;
	            posX = Math.cos(curAngle) * radius;
	            posY = halfHeight;
	            posZ = Math.sin(curAngle) * radius;
	            vertices[vc++] = posX;
	            vertices[vc++] = posY;
	            vertices[vc++] = posZ;
	            vertices[vc++] = 0;
	            vertices[vc++] = 1;
	            vertices[vc++] = 0;
	            vertices[vc++] = 0.5 + Math.cos(curAngle) * 0.5;
	            vertices[vc++] = 0.5 + Math.sin(curAngle) * 0.5;
	        }
	        for (var ti = 0; ti < slices; ti++) {
	            indices[ic++] = 0;
	            indices[ic++] = ti + 1;
	            indices[ic++] = ti + 2;
	        }
	        verticeCount += slices + 1 + 1;
	        for (var rv = 0; rv <= slices; rv++) {
	            curAngle = rv * sliceAngle;
	            posX = Math.cos(curAngle + Math.PI) * radius;
	            posY = halfHeight;
	            posZ = Math.sin(curAngle + Math.PI) * radius;
	            vertices[vc++] = posX;
	            vertices[vc + (slices + 1) * 8 - 1] = posX;
	            vertices[vc++] = posY;
	            vertices[vc + (slices + 1) * 8 - 1] = -posY;
	            vertices[vc++] = posZ;
	            vertices[vc + (slices + 1) * 8 - 1] = posZ;
	            vertices[vc++] = posX;
	            vertices[vc + (slices + 1) * 8 - 1] = posX;
	            vertices[vc++] = 0;
	            vertices[vc + (slices + 1) * 8 - 1] = 0;
	            vertices[vc++] = posZ;
	            vertices[vc + (slices + 1) * 8 - 1] = posZ;
	            vertices[vc++] = 1 - rv * 1 / slices;
	            vertices[vc + (slices + 1) * 8 - 1] = 1 - rv * 1 / slices;
	            vertices[vc++] = 0;
	            vertices[vc + (slices + 1) * 8 - 1] = 1;
	        }
	        vc += (slices + 1) * 8;
	        for (var ri = 0; ri < slices; ri++) {
	            indices[ic++] = ri + verticeCount + (slices + 1);
	            indices[ic++] = ri + verticeCount + 1;
	            indices[ic++] = ri + verticeCount;
	            indices[ic++] = ri + verticeCount + (slices + 1);
	            indices[ic++] = ri + verticeCount + (slices + 1) + 1;
	            indices[ic++] = ri + verticeCount + 1;
	        }
	        verticeCount += 2 * (slices + 1);
	        for (var bv = 0; bv <= slices; bv++) {
	            if (bv === 0) {
	                vertices[vc++] = 0;
	                vertices[vc++] = -halfHeight;
	                vertices[vc++] = 0;
	                vertices[vc++] = 0;
	                vertices[vc++] = -1;
	                vertices[vc++] = 0;
	                vertices[vc++] = 0.5;
	                vertices[vc++] = 0.5;
	            }
	            curAngle = bv * sliceAngle;
	            posX = Math.cos(curAngle + Math.PI) * radius;
	            posY = -halfHeight;
	            posZ = Math.sin(curAngle + Math.PI) * radius;
	            vertices[vc++] = posX;
	            vertices[vc++] = posY;
	            vertices[vc++] = posZ;
	            vertices[vc++] = 0;
	            vertices[vc++] = -1;
	            vertices[vc++] = 0;
	            vertices[vc++] = 0.5 + Math.cos(curAngle) * 0.5;
	            vertices[vc++] = 0.5 + Math.sin(curAngle) * 0.5;
	        }
	        for (var bi = 0; bi < slices; bi++) {
	            indices[ic++] = 0 + verticeCount;
	            indices[ic++] = bi + 2 + verticeCount;
	            indices[ic++] = bi + 1 + verticeCount;
	        }
	        verticeCount += slices + 1 + 1;
	        return PrimitiveMesh._createMesh(vertexDeclaration, vertices, indices);
	    }
	    static createPlane(long = 10, width = 10, stacks = 10, slices = 10) {
	        var vertexCount = (stacks + 1) * (slices + 1);
	        var indexCount = stacks * slices * 2 * 3;
	        var indices = new Uint16Array(indexCount);
	        var vertexDeclaration = VertexMesh.getVertexDeclaration("POSITION,NORMAL,UV");
	        var vertexFloatStride = vertexDeclaration.vertexStride / 4;
	        var vertices = new Float32Array(vertexCount * vertexFloatStride);
	        var halfLong = long / 2;
	        var halfWidth = width / 2;
	        var stacksLong = long / stacks;
	        var slicesWidth = width / slices;
	        var verticeCount = 0;
	        for (var i = 0; i <= slices; i++) {
	            for (var j = 0; j <= stacks; j++) {
	                vertices[verticeCount++] = j * stacksLong - halfLong;
	                vertices[verticeCount++] = 0;
	                vertices[verticeCount++] = i * slicesWidth - halfWidth;
	                vertices[verticeCount++] = 0;
	                vertices[verticeCount++] = 1;
	                vertices[verticeCount++] = 0;
	                vertices[verticeCount++] = j * 1 / stacks;
	                vertices[verticeCount++] = i * 1 / slices;
	            }
	        }
	        var indiceIndex = 0;
	        for (i = 0; i < slices; i++) {
	            for (j = 0; j < stacks; j++) {
	                indices[indiceIndex++] = (i + 1) * (stacks + 1) + j;
	                indices[indiceIndex++] = i * (stacks + 1) + j;
	                indices[indiceIndex++] = (i + 1) * (stacks + 1) + j + 1;
	                indices[indiceIndex++] = i * (stacks + 1) + j;
	                indices[indiceIndex++] = i * (stacks + 1) + j + 1;
	                indices[indiceIndex++] = (i + 1) * (stacks + 1) + j + 1;
	            }
	        }
	        return PrimitiveMesh._createMesh(vertexDeclaration, vertices, indices);
	    }
	    static createQuad(long = 1, width = 1) {
	        var vertexDeclaration = VertexMesh.getVertexDeclaration("POSITION,NORMAL,UV");
	        var halfLong = long / 2;
	        var halfWidth = width / 2;
	        var vertices = new Float32Array([-halfLong, halfWidth, 0, 0, 0, 1, 0, 0, halfLong, halfWidth, 0, 0, 0, 1, 1, 0, -halfLong, -halfWidth, 0, 0, 0, 1, 0, 1, halfLong, -halfWidth, 0, 0, 0, 1, 1, 1]);
	        var indices = new Uint16Array([0, 1, 2, 3, 2, 1]);
	        return PrimitiveMesh._createMesh(vertexDeclaration, vertices, indices);
	    }
	    static createSphere(radius = 0.5, stacks = 32, slices = 32) {
	        var vertexCount = (stacks + 1) * (slices + 1);
	        var indexCount = (3 * stacks * (slices + 1)) * 2;
	        var indices = new Uint16Array(indexCount);
	        var vertexDeclaration = VertexMesh.getVertexDeclaration("POSITION,NORMAL,UV");
	        var vertexFloatStride = vertexDeclaration.vertexStride / 4;
	        var vertices = new Float32Array(vertexCount * vertexFloatStride);
	        var stackAngle = Math.PI / stacks;
	        var sliceAngle = (Math.PI * 2.0) / slices;
	        var vertexIndex = 0;
	        vertexCount = 0;
	        indexCount = 0;
	        for (var stack = 0; stack < (stacks + 1); stack++) {
	            var r = Math.sin(stack * stackAngle);
	            var y = Math.cos(stack * stackAngle);
	            for (var slice = 0; slice < (slices + 1); slice++) {
	                var x = r * Math.sin(slice * sliceAngle + Math.PI * 1 / 2);
	                var z = r * Math.cos(slice * sliceAngle + Math.PI * 1 / 2);
	                vertices[vertexCount + 0] = x * radius;
	                vertices[vertexCount + 1] = y * radius;
	                vertices[vertexCount + 2] = z * radius;
	                vertices[vertexCount + 3] = x;
	                vertices[vertexCount + 4] = y;
	                vertices[vertexCount + 5] = z;
	                vertices[vertexCount + 6] = slice / slices;
	                vertices[vertexCount + 7] = stack / stacks;
	                vertexCount += vertexFloatStride;
	                if (stack != (stacks - 1)) {
	                    indices[indexCount++] = vertexIndex + (slices + 1);
	                    indices[indexCount++] = vertexIndex;
	                    indices[indexCount++] = vertexIndex + 1;
	                    indices[indexCount++] = vertexIndex + (slices);
	                    indices[indexCount++] = vertexIndex;
	                    indices[indexCount++] = vertexIndex + (slices + 1);
	                    vertexIndex++;
	                }
	            }
	        }
	        return PrimitiveMesh._createMesh(vertexDeclaration, vertices, indices);
	    }
	}

	class TextureCube extends Laya.BaseTexture {
	    constructor(size, format = Laya.TextureFormat.R8G8B8, mipmap = false) {
	        super(format, mipmap);
	        this._glTextureType = Laya.LayaGL.instance.TEXTURE_CUBE_MAP;
	        this._width = size;
	        this._height = size;
	        var gl = Laya.LayaGL.instance;
	        this._setWarpMode(gl.TEXTURE_WRAP_S, this._wrapModeU);
	        this._setWarpMode(gl.TEXTURE_WRAP_T, this._wrapModeV);
	        this._setFilterMode(this._filterMode);
	        this._setAnisotropy(this._anisoLevel);
	        if (this._mipmap) {
	            this._mipmapCount = Math.ceil(Math.log2(size));
	            for (var i = 0; i < this._mipmapCount; i++)
	                this._setPixels([], i, Math.max(size >> i, 1), Math.max(size >> i, 1));
	            this._setGPUMemory(size * size * 4 * (1 + 1 / 3) * 6);
	        }
	        else {
	            this._mipmapCount = 1;
	            this._setGPUMemory(size * size * 4 * 6);
	        }
	    }
	    static __init__() {
	        var pixels = new Uint8Array(3);
	        pixels[0] = 128;
	        pixels[1] = 128;
	        pixels[2] = 128;
	        TextureCube.grayTexture = new TextureCube(1, Laya.TextureFormat.R8G8B8, false);
	        TextureCube.grayTexture.setSixSidePixels([pixels, pixels, pixels, pixels, pixels, pixels]);
	        TextureCube.grayTexture.lock = true;
	    }
	    static _parse(data, propertyParams = null, constructParams = null) {
	        var texture = constructParams ? new TextureCube(0, constructParams[0], constructParams[1]) : new TextureCube(0);
	        texture.setSixSideImageSources(data);
	        return texture;
	    }
	    static load(url, complete) {
	        Laya.ILaya.loader.create(url, complete, null, TextureCube.TEXTURECUBE);
	    }
	    get defaulteTexture() {
	        return TextureCube.grayTexture;
	    }
	    _setPixels(pixels, miplevel, width, height) {
	        var gl = Laya.LayaGL.instance;
	        var glFormat = this._getGLFormat();
	        Laya.WebGLContext.bindTexture(gl, this._glTextureType, this._glTexture);
	        if (this.format === Laya.TextureFormat.R8G8B8) {
	            gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
	            gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, miplevel, glFormat, width, height, 0, glFormat, gl.UNSIGNED_BYTE, pixels[0]);
	            gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, miplevel, glFormat, width, height, 0, glFormat, gl.UNSIGNED_BYTE, pixels[1]);
	            gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, miplevel, glFormat, width, height, 0, glFormat, gl.UNSIGNED_BYTE, pixels[2]);
	            gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, miplevel, glFormat, width, height, 0, glFormat, gl.UNSIGNED_BYTE, pixels[3]);
	            gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, miplevel, glFormat, width, height, 0, glFormat, gl.UNSIGNED_BYTE, pixels[4]);
	            gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, miplevel, glFormat, width, height, 0, glFormat, gl.UNSIGNED_BYTE, pixels[5]);
	            gl.pixelStorei(gl.UNPACK_ALIGNMENT, 4);
	        }
	        else {
	            gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, miplevel, glFormat, width, height, 0, glFormat, gl.UNSIGNED_BYTE, pixels[0]);
	            gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, miplevel, glFormat, width, height, 0, glFormat, gl.UNSIGNED_BYTE, pixels[1]);
	            gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, miplevel, glFormat, width, height, 0, glFormat, gl.UNSIGNED_BYTE, pixels[2]);
	            gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, miplevel, glFormat, width, height, 0, glFormat, gl.UNSIGNED_BYTE, pixels[3]);
	            gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, miplevel, glFormat, width, height, 0, glFormat, gl.UNSIGNED_BYTE, pixels[4]);
	            gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, miplevel, glFormat, width, height, 0, glFormat, gl.UNSIGNED_BYTE, pixels[5]);
	        }
	    }
	    setSixSideImageSources(source, premultiplyAlpha = false) {
	        var width;
	        var height;
	        for (var i = 0; i < 6; i++) {
	            var img = source[i];
	            if (!img) {
	                console.log("TextureCube: image Source can't be null.");
	                return;
	            }
	            var nextWidth = img.width;
	            var nextHeight = img.height;
	            if (i > 0) {
	                if (width !== nextWidth) {
	                    console.log("TextureCube: each side image's width and height must same.");
	                    return;
	                }
	            }
	            width = nextWidth;
	            height = nextHeight;
	            if (width !== height) {
	                console.log("TextureCube: each side image's width and height must same.");
	                return;
	            }
	        }
	        this._width = width;
	        this._height = height;
	        var gl = Laya.LayaGL.instance;
	        Laya.WebGLContext.bindTexture(gl, this._glTextureType, this._glTexture);
	        var glFormat = this._getGLFormat();
	        if (!Laya.Render.isConchApp) {
	            (premultiplyAlpha) && (gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true));
	            gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, glFormat, glFormat, gl.UNSIGNED_BYTE, source[0]);
	            gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, glFormat, glFormat, gl.UNSIGNED_BYTE, source[1]);
	            gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, glFormat, glFormat, gl.UNSIGNED_BYTE, source[2]);
	            gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, glFormat, glFormat, gl.UNSIGNED_BYTE, source[3]);
	            gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, glFormat, glFormat, gl.UNSIGNED_BYTE, source[4]);
	            gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, glFormat, glFormat, gl.UNSIGNED_BYTE, source[5]);
	            (premultiplyAlpha) && (gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false));
	        }
	        else {
	            if (premultiplyAlpha == true) {
	                for (var j = 0; j < 6; j++)
	                    source[j].setPremultiplyAlpha(premultiplyAlpha);
	            }
	            gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source[0]);
	            gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source[1]);
	            gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source[2]);
	            gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source[3]);
	            gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source[4]);
	            gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source[5]);
	        }
	        if (this._mipmap && this._isPot(width) && this._isPot(height)) {
	            gl.generateMipmap(this._glTextureType);
	            this._setGPUMemory(width * height * 4 * (1 + 1 / 3) * 6);
	        }
	        else {
	            this._setGPUMemory(width * height * 4 * 6);
	        }
	        this._setWarpMode(gl.TEXTURE_WRAP_S, this._wrapModeU);
	        this._setWarpMode(gl.TEXTURE_WRAP_T, this._wrapModeV);
	        this._setFilterMode(this._filterMode);
	        this._readyed = true;
	        this._activeResource();
	    }
	    setSixSidePixels(pixels, miplevel = 0) {
	        if (!pixels)
	            throw new Error("TextureCube:pixels can't be null.");
	        var width = Math.max(this._width >> miplevel, 1);
	        var height = Math.max(this._height >> miplevel, 1);
	        var pixelsCount = width * height * this._getFormatByteCount();
	        if (pixels[0].length < pixelsCount)
	            throw "TextureCube:pixels length should at least " + pixelsCount + ".";
	        this._setPixels(pixels, miplevel, width, height);
	        if (miplevel === 0) {
	            var gl = Laya.LayaGL.instance;
	            this._setWarpMode(gl.TEXTURE_WRAP_S, this._wrapModeU);
	            this._setWarpMode(gl.TEXTURE_WRAP_T, this._wrapModeV);
	        }
	        this._readyed = true;
	        this._activeResource();
	    }
	    _recoverResource() {
	    }
	}
	TextureCube.TEXTURECUBE = "TEXTURECUBE";

	var BlitScreenPS = "#ifdef FSHIGHPRECISION\r\n\tprecision highp float;\r\n#else\r\n\tprecision mediump float;\r\n#endif\r\n\r\nuniform sampler2D u_MainTex;\r\nvarying vec2 v_Texcoord0;\r\n\r\nvoid main() {\r\n\tgl_FragColor = texture2D(u_MainTex, v_Texcoord0);\r\n}\r\n\r\n";

	var BlitScreenVS = "#include \"Lighting.glsl\";\r\n\r\nattribute vec4 a_PositionTexcoord;\r\nvarying vec2 v_Texcoord0;\r\n\r\nvoid main() {\r\n\tgl_Position = vec4(a_PositionTexcoord.xy, 0.0, 1.0);\r\n\tv_Texcoord0 = a_PositionTexcoord.zw;\r\n\tgl_Position = remapGLPositionZ(gl_Position);\r\n}";

	var EffectPS = "#ifdef HIGHPRECISION\r\n\tprecision highp float;\r\n#else\r\n\tprecision mediump float;\r\n#endif\r\n\r\n#ifdef COLOR\r\n\tvarying vec4 v_Color;\r\n#endif\r\nvarying vec2 v_Texcoord0;\r\n\r\n#ifdef MAINTEXTURE\r\n\tuniform sampler2D u_AlbedoTexture;\r\n#endif\r\n\r\nuniform vec4 u_AlbedoColor;\r\n\r\n#ifdef FOG\r\n\tuniform float u_FogStart;\r\n\tuniform float u_FogRange;\r\n\t#ifdef ADDTIVEFOG\r\n\t#else\r\n\t\tuniform vec3 u_FogColor;\r\n\t#endif\r\n#endif\r\n\r\nvoid main()\r\n{\r\n\tvec4 color =  2.0 * u_AlbedoColor;\r\n\t#ifdef COLOR\r\n\t\tcolor *= v_Color;\r\n\t#endif\r\n\t#ifdef MAINTEXTURE\r\n\t\tcolor *= texture2D(u_AlbedoTexture, v_Texcoord0);\r\n\t#endif\r\n\t\r\n\tgl_FragColor = color;\r\n\t\r\n\t#ifdef FOG\r\n\t\tfloat lerpFact = clamp((1.0 / gl_FragCoord.w - u_FogStart) / u_FogRange, 0.0, 1.0);\r\n\t\t#ifdef ADDTIVEFOG\r\n\t\t\tgl_FragColor.rgb = mix(gl_FragColor.rgb, vec3(0.0), lerpFact);\r\n\t\t#else\r\n\t\t\tgl_FragColor.rgb = mix(gl_FragColor.rgb, u_FogColor, lerpFact);\r\n\t\t#endif\r\n\t#endif\r\n}\r\n\r\n";

	var EffectVS = "#include \"Lighting.glsl\";\r\n\r\nattribute vec4 a_Position;\r\nattribute vec4 a_Color;\r\nattribute vec2 a_Texcoord0;\r\n\r\n#ifdef GPU_INSTANCE\r\n\tattribute mat4 a_MvpMatrix;\r\n#else\r\n\tuniform mat4 u_MvpMatrix;\r\n#endif\r\n\r\n#ifdef COLOR\r\n\tvarying vec4 v_Color;\r\n#endif\r\nvarying vec2 v_Texcoord0;\r\n\r\n#ifdef TILINGOFFSET\r\n\tuniform vec4 u_TilingOffset;\r\n#endif\r\n\r\n#ifdef BONE\r\n\tconst int c_MaxBoneCount = 24;\r\n\tattribute vec4 a_BoneIndices;\r\n\tattribute vec4 a_BoneWeights;\r\n\tuniform mat4 u_Bones[c_MaxBoneCount];\r\n#endif\r\n\r\nvoid main()\r\n{\r\n\tvec4 position;\r\n\t#ifdef BONE\r\n\t\tmat4 skinTransform = u_Bones[int(a_BoneIndices.x)] * a_BoneWeights.x;\r\n\t\tskinTransform += u_Bones[int(a_BoneIndices.y)] * a_BoneWeights.y;\r\n\t\tskinTransform += u_Bones[int(a_BoneIndices.z)] * a_BoneWeights.z;\r\n\t\tskinTransform += u_Bones[int(a_BoneIndices.w)] * a_BoneWeights.w;\r\n\t\tposition=skinTransform*a_Position;\r\n\t#else\r\n\t\tposition=a_Position;\r\n\t#endif\r\n\t#ifdef GPU_INSTANCE\r\n\t\tgl_Position = a_MvpMatrix * position;\r\n\t#else\r\n\t\tgl_Position = u_MvpMatrix * position;\r\n\t#endif\r\n\t\r\n\t#ifdef TILINGOFFSET\r\n\t\tv_Texcoord0=TransformUV(a_Texcoord0,u_TilingOffset);\r\n\t#else\r\n\t\tv_Texcoord0=a_Texcoord0;\r\n\t#endif\r\n\t\t\r\n\t#ifdef COLOR\r\n\t\tv_Color = a_Color;\r\n\t#endif\r\n\tgl_Position=remapGLPositionZ(gl_Position);\r\n}";

	var extendTerrainPS = "#ifdef HIGHPRECISION\r\n\tprecision highp float;\r\n#else\r\n\tprecision mediump float;\r\n#endif\r\n\r\n#include \"Lighting.glsl\";\r\n\r\n#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)||defined(FOG)\r\n\tuniform vec3 u_CameraPos;\r\n\tvarying vec3 v_Normal;\r\n\tvarying vec3 v_PositionWorld;\r\n#endif\r\n\r\n#ifdef FOG\r\n\tuniform float u_FogStart;\r\n\tuniform float u_FogRange;\r\n\tuniform vec3 u_FogColor;\r\n#endif\r\n\r\n\r\n#ifdef DIRECTIONLIGHT\r\n\tuniform DirectionLight u_DirectionLight;\r\n#endif\r\n\r\n#ifdef POINTLIGHT\r\n\tuniform PointLight u_PointLight;\r\n#endif\r\n\r\n#ifdef SPOTLIGHT\r\n\tuniform SpotLight u_SpotLight;\r\n#endif\r\n\r\n#include \"ShadowHelper.glsl\"\r\n#ifdef RECEIVESHADOW\r\n\t#if defined(SHADOWMAP_PSSM2)||defined(SHADOWMAP_PSSM3)\r\n\tuniform mat4 u_lightShadowVP[4];\r\n\t#endif\r\n\t#ifdef SHADOWMAP_PSSM1 \r\n\tvarying vec4 v_lightMVPPos;\r\n\t#endif\r\n#endif\r\nvarying float v_posViewZ;\r\n\r\nuniform vec3 u_AmbientColor;\r\n\r\nuniform sampler2D u_SplatAlphaTexture;\r\n\r\nuniform sampler2D u_DiffuseTexture1;\r\nuniform sampler2D u_DiffuseTexture2;\r\nuniform sampler2D u_DiffuseTexture3;\r\nuniform sampler2D u_DiffuseTexture4;\r\nuniform sampler2D u_DiffuseTexture5;\r\n\r\nuniform vec4 u_DiffuseScaleOffset1;\r\nuniform vec4 u_DiffuseScaleOffset2;\r\nuniform vec4 u_DiffuseScaleOffset3;\r\nuniform vec4 u_DiffuseScaleOffset4;\r\nuniform vec4 u_DiffuseScaleOffset5;\r\n\r\nvarying vec2 v_Texcoord0;\r\n\r\n#ifdef LIGHTMAP\r\n\tuniform sampler2D u_LightMap;\r\n\tvarying vec2 v_LightMapUV;\r\n#endif\r\n\r\nvoid main()\r\n{\r\n\tvec4 splatAlpha = vec4(1.0);\r\n\t#ifdef ExtendTerrain_DETAIL_NUM1\r\n\t\tsplatAlpha = texture2D(u_SplatAlphaTexture, v_Texcoord0);\r\n\t\tvec4 color1 = texture2D(u_DiffuseTexture1, v_Texcoord0 * u_DiffuseScaleOffset1.xy);\r\n\t\tgl_FragColor.xyz = color1.xyz * splatAlpha.r;\r\n\t#endif\r\n\t#ifdef ExtendTerrain_DETAIL_NUM2\r\n\t\tsplatAlpha = texture2D(u_SplatAlphaTexture, v_Texcoord0);\r\n\t\tvec4 color1 = texture2D(u_DiffuseTexture1, v_Texcoord0 * u_DiffuseScaleOffset1.xy);\r\n\t\tvec4 color2 = texture2D(u_DiffuseTexture2, v_Texcoord0 * u_DiffuseScaleOffset2.xy);\r\n\t\tgl_FragColor.xyz = color1.xyz * splatAlpha.r + color2.xyz * (1.0 - splatAlpha.r);\r\n\t#endif\r\n\t#ifdef ExtendTerrain_DETAIL_NUM3\r\n\t\tsplatAlpha = texture2D(u_SplatAlphaTexture, v_Texcoord0);\r\n\t\tvec4 color1 = texture2D(u_DiffuseTexture1, v_Texcoord0 * u_DiffuseScaleOffset1.xy);\r\n\t\tvec4 color2 = texture2D(u_DiffuseTexture2, v_Texcoord0 * u_DiffuseScaleOffset2.xy);\r\n\t\tvec4 color3 = texture2D(u_DiffuseTexture3, v_Texcoord0 * u_DiffuseScaleOffset3.xy);\r\n\t\tgl_FragColor.xyz = color1.xyz * splatAlpha.r  + color2.xyz * splatAlpha.g + color3.xyz * (1.0 - splatAlpha.r - splatAlpha.g);\r\n\t#endif\r\n\t#ifdef ExtendTerrain_DETAIL_NUM4\r\n\t\tsplatAlpha = texture2D(u_SplatAlphaTexture, v_Texcoord0);\r\n\t\tvec4 color1 = texture2D(u_DiffuseTexture1, v_Texcoord0 * u_DiffuseScaleOffset1.xy);\r\n\t\tvec4 color2 = texture2D(u_DiffuseTexture2, v_Texcoord0 * u_DiffuseScaleOffset2.xy);\r\n\t\tvec4 color3 = texture2D(u_DiffuseTexture3, v_Texcoord0 * u_DiffuseScaleOffset3.xy);\r\n\t\tvec4 color4 = texture2D(u_DiffuseTexture4, v_Texcoord0 * u_DiffuseScaleOffset4.xy);\r\n\t\tgl_FragColor.xyz = color1.xyz * splatAlpha.r  + color2.xyz * splatAlpha.g + color3.xyz * splatAlpha.b + color4.xyz * (1.0 - splatAlpha.r - splatAlpha.g - splatAlpha.b);\r\n\t#endif\r\n\t#ifdef ExtendTerrain_DETAIL_NUM5\r\n\t\tsplatAlpha = texture2D(u_SplatAlphaTexture, v_Texcoord0);\r\n\t\tvec4 color1 = texture2D(u_DiffuseTexture1, v_Texcoord0 * u_DiffuseScaleOffset1.xy);\r\n\t\tvec4 color2 = texture2D(u_DiffuseTexture2, v_Texcoord0 * u_DiffuseScaleOffset2.xy);\r\n\t\tvec4 color3 = texture2D(u_DiffuseTexture3, v_Texcoord0 * u_DiffuseScaleOffset3.xy);\r\n\t\tvec4 color4 = texture2D(u_DiffuseTexture4, v_Texcoord0 * u_DiffuseScaleOffset4.xy);\r\n\t\tvec4 color5 = texture2D(u_DiffuseTexture5, v_Texcoord0 * u_DiffuseScaleOffset5.xy);\r\n\t\tgl_FragColor.xyz = color1.xyz * splatAlpha.r  + color2.xyz * splatAlpha.g + color3.xyz * splatAlpha.b + color4.xyz * splatAlpha.a + color5.xyz * (1.0 - splatAlpha.r - splatAlpha.g - splatAlpha.b - splatAlpha.a);\r\n\t#endif\r\n\t\tgl_FragColor.w = splatAlpha.a;\r\n\t\t\r\n#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)\r\n    vec3 normal = v_Normal;\r\n\tvec3 dif, spe;\r\n#endif\r\n\r\nvec3 diffuse = vec3(0.0);\r\nvec3 specular= vec3(0.0);\r\n#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)||defined(FOG)\r\n\tvec3 toEye;\r\n\t#ifdef FOG\r\n\t\ttoEye=u_CameraPos-v_PositionWorld;\r\n\t\tfloat toEyeLength=length(toEye);\r\n\t\ttoEye/=toEyeLength;\r\n\t#else\r\n\t\ttoEye=normalize(u_CameraPos-v_PositionWorld);\r\n\t#endif\r\n#endif\r\n\r\n#ifdef DIRECTIONLIGHT\r\n\tLayaAirBlinnPhongDiectionLight(vec3(0.0), 1.0, normal, vec3(1.0), toEye,u_DirectionLight, dif, spe);\r\n\tdiffuse+=dif;\r\n\tspecular+=spe;\r\n#endif\r\n \r\n#ifdef POINTLIGHT\r\n\tLayaAirBlinnPhongPointLight(v_PositionWorld, vec3(0.0), 1.0, normal, vec3(1.0), toEye, u_PointLight, dif, spe);\r\n\tdiffuse+=dif;\r\n\tspecular+=spe;\r\n#endif\r\n\r\n#ifdef SPOTLIGHT\r\n\tLayaAirBlinnPhongSpotLight(v_PositionWorld, vec3(0.0), 1.0, normal, vec3(1.0), toEye, u_SpotLight, dif, spe);\r\n\tdiffuse+=dif;\r\n\tspecular+=spe;\r\n#endif\r\n\r\nvec3 globalDiffuse = u_AmbientColor;\r\n#ifdef LIGHTMAP\r\n\tglobalDiffuse += DecodeLightmap(texture2D(u_LightMap, v_LightMapUV));\r\n#endif\r\n\r\n#ifdef RECEIVESHADOW\r\n\tfloat shadowValue = 1.0;\r\n\t#ifdef SHADOWMAP_PSSM3\r\n\t\tshadowValue = getShadowPSSM3( u_shadowMap1,u_shadowMap2,u_shadowMap3,u_lightShadowVP,u_shadowPSSMDistance,u_shadowPCFoffset,v_PositionWorld,v_posViewZ,0.001);\r\n\t#endif\r\n\t#ifdef SHADOWMAP_PSSM2\r\n\t\tshadowValue = getShadowPSSM2( u_shadowMap1,u_shadowMap2,u_lightShadowVP,u_shadowPSSMDistance,u_shadowPCFoffset,v_PositionWorld,v_posViewZ,0.001);\r\n\t#endif \r\n\t#ifdef SHADOWMAP_PSSM1\r\n\t\tshadowValue = getShadowPSSM1( u_shadowMap1,v_lightMVPPos,u_shadowPSSMDistance,u_shadowPCFoffset,v_posViewZ,0.001);\r\n\t#endif\r\n\tgl_FragColor = vec4(gl_FragColor.rgb * (globalDiffuse + diffuse) * shadowValue, gl_FragColor.a);\r\n#else\r\n\tgl_FragColor = vec4(gl_FragColor.rgb * (globalDiffuse + diffuse), gl_FragColor.a);\r\n#endif\r\n\r\n#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)\r\n\t#ifdef RECEIVESHADOW\r\n\t\tgl_FragColor.rgb += specular * shadowValue;\r\n\t#else\r\n\t\tgl_FragColor.rgb += specular;\r\n\t#endif\r\n#endif\r\n\r\n#ifdef FOG\r\n\tfloat lerpFact=clamp((toEyeLength-u_FogStart)/u_FogRange,0.0,1.0);\r\n\tgl_FragColor.rgb=mix(gl_FragColor.rgb,u_FogColor,lerpFact);\r\n#endif\r\n}\r\n\r\n\r\n\r\n\r\n\r\n";

	var extendTerrainVS = "#include \"Lighting.glsl\";\r\n\r\nattribute vec4 a_Position;\r\nattribute vec2 a_Texcoord0;\r\n\r\nuniform mat4 u_MvpMatrix;\r\n\r\nvarying vec2 v_Texcoord0;\r\n\r\n#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)||defined(LIGHTMAP)\r\n\tattribute vec3 a_Normal;\r\n\tvarying vec3 v_Normal;\r\n#endif\r\n\r\n#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)||defined(FOG)||(defined(RECEIVESHADOW)&&defined(SHADOWMAP_PSSM1))\r\n\tuniform mat4 u_WorldMat;\r\n\tvarying vec3 v_PositionWorld;\r\n#endif\r\n\r\n#ifdef LIGHTMAP\r\n\tvarying vec2 v_LightMapUV;\r\n\tuniform vec4 u_LightmapScaleOffset;\r\n#endif\r\n\r\n#ifdef RECEIVESHADOW\r\n\tvarying float v_posViewZ;\r\n\t#ifdef SHADOWMAP_PSSM1 \r\n\t\tvarying vec4 v_lightMVPPos;\r\n\t\tuniform mat4 u_lightShadowVP[4];\r\n\t#endif\r\n#endif\r\n\r\nvoid main()\r\n{\r\n\tgl_Position = u_MvpMatrix * a_Position;\r\n  \r\n\tv_Texcoord0 = a_Texcoord0;\r\n  \r\n\t#ifdef LIGHTMAP\r\n\t\tv_LightMapUV = vec2(a_Texcoord0.x, 1.0 - a_Texcoord0.y) * u_LightmapScaleOffset.xy + u_LightmapScaleOffset.zw;\r\n\t\tv_LightMapUV.y = 1.0 - v_LightMapUV.y;\r\n\t#endif\r\n  \r\n\t#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)\r\n\t\tv_Normal = a_Normal;\r\n\t#endif\r\n\r\n\t#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)||defined(FOG)||(defined(RECEIVESHADOW)&&defined(SHADOWMAP_PSSM1))\r\n\t\tv_PositionWorld=(u_WorldMat*a_Position).xyz;\r\n\t#endif\r\n\r\n\t#ifdef RECEIVESHADOW\r\n\t\tv_posViewZ = gl_Position.w;\r\n\t\t#ifdef SHADOWMAP_PSSM1\r\n\t\t\tv_lightMVPPos = u_lightShadowVP[0] * vec4(v_PositionWorld,1.0);\r\n\t\t#endif\r\n\t#endif\r\n\tgl_Position=remapGLPositionZ(gl_Position);\r\n}";

	var LightingGLSL = "struct DirectionLight {\r\n\tvec3 color;\r\n\tvec3 direction;\r\n};\r\n\r\nstruct PointLight {\r\n\tvec3 color;\r\n\tvec3 position;\r\n\tfloat range;\r\n};\r\n\r\nstruct SpotLight {\r\n\tvec3 color;\r\n\tvec3 position;\r\n\tfloat range;\r\n\tvec3 direction;\r\n\tfloat spot;\r\n};\r\n\r\n\r\n\r\nconst int c_ClusterBufferWidth = CLUSTER_X_COUNT*CLUSTER_Y_COUNT;\r\nconst int c_ClusterBufferHeight = CLUSTER_Z_COUNT*(1+int(ceil(float(MAX_LIGHT_COUNT_PER_CLUSTER)/4.0)));\r\nconst int c_ClusterBufferFloatWidth = c_ClusterBufferWidth*4;\r\n\r\nivec4 getClusterInfo(sampler2D clusterBuffer,mat4 viewMatrix,vec4 viewport,vec3 position,vec4 fragCoord,vec4 projectParams)\r\n{\r\n\tvec3 viewPos = vec3(viewMatrix*vec4(position, 1.0)); //position in viewspace\r\n\r\n\tint clusterXIndex = int(floor(fragCoord.x/ (float(viewport.z)/float(CLUSTER_X_COUNT))));\r\n    int clusterYIndex = int(floor((viewport.w * (projectParams.z <0.0? 0.0 : 1.0) - fragCoord.y * projectParams.z)/ (float(viewport.w)/float(CLUSTER_Y_COUNT))));//Maybe Flipped ProjectMatrix\r\n\tfloat zSliceParam =float(CLUSTER_Z_COUNT)/log2(projectParams.y / projectParams.x);\r\n \tint clusterZIndex = int(floor(log2(-viewPos.z) * zSliceParam- log2(projectParams.x) * zSliceParam));//projectParams x:cameraNear y:cameraFar\r\n\r\n\tvec2 uv= vec2((float(clusterXIndex + clusterYIndex * CLUSTER_X_COUNT)+0.5)/float(c_ClusterBufferWidth),\r\n\t\t\t\t(float(clusterZIndex)+0.5)/float(c_ClusterBufferHeight));\r\n\tvec4 clusterPixel=texture2D(clusterBuffer, uv);\r\n\treturn ivec4(clusterPixel);//X:Point Count Y:Spot Count Z、W:Light Offset\r\n}\r\n\r\n\r\nint getLightIndex(sampler2D clusterBuffer,int offset,int index) \r\n{\r\n\tint totalOffset=offset+index;\r\n\tint row=totalOffset/c_ClusterBufferFloatWidth;\r\n\tint lastRowFloat=totalOffset-row*c_ClusterBufferFloatWidth;\r\n\tint col=lastRowFloat/4;\r\n\tvec2 uv=vec2((float(col)+0.5)/float(c_ClusterBufferWidth),\r\n\t\t\t\t(float(row)+0.5)/float(c_ClusterBufferHeight));\r\n\tvec4 texel = texture2D(clusterBuffer, uv);\r\n    int pixelComponent = lastRowFloat-col*4;\r\n    if (pixelComponent == 0) \r\n      return int(texel.x);\r\n    else if (pixelComponent == 1) \r\n      return int(texel.y);\r\n    else if (pixelComponent == 2) \r\n      return int(texel.z);\r\n    else if (pixelComponent == 3) \r\n      return int(texel.w);\r\n}\r\n\r\nDirectionLight getDirectionLight(sampler2D lightBuffer,int index) \r\n{\r\n    DirectionLight light;\r\n    float v = (float(index)+0.5)/ float(MAX_LIGHT_COUNT);\r\n    vec4 p1 = texture2D(lightBuffer, vec2(0.125,v));\r\n    vec4 p2 = texture2D(lightBuffer, vec2(0.375,v));\r\n\tlight.color=p1.rgb;\r\n    light.direction = p2.rgb;\r\n    return light;\r\n}\r\n\r\nPointLight getPointLight(sampler2D lightBuffer,sampler2D clusterBuffer,ivec4 clusterInfo,int index) \r\n{\r\n    PointLight light;\r\n\tint pointIndex=getLightIndex(clusterBuffer,clusterInfo.z*c_ClusterBufferFloatWidth+clusterInfo.w,index);\r\n    float v = (float(pointIndex)+0.5)/ float(MAX_LIGHT_COUNT);\r\n    vec4 p1 = texture2D(lightBuffer, vec2(0.125,v));\r\n    vec4 p2 = texture2D(lightBuffer, vec2(0.375,v));\r\n\tlight.color=p1.rgb;\r\n\tlight.range = p1.a;\r\n    light.position = p2.rgb;\r\n    return light;\r\n}\r\n\r\nSpotLight getSpotLight(sampler2D lightBuffer,sampler2D clusterBuffer,ivec4 clusterInfo,int index) \r\n{\r\n    SpotLight light;\r\n\tint spoIndex=getLightIndex(clusterBuffer,clusterInfo.z*c_ClusterBufferFloatWidth+clusterInfo.w,clusterInfo.x+index);\r\n    float v = (float(spoIndex)+0.5)/ float(MAX_LIGHT_COUNT);\r\n    vec4 p1 = texture2D(lightBuffer, vec2(0.125,v));\r\n    vec4 p2 = texture2D(lightBuffer, vec2(0.375,v));\r\n\tvec4 p3 = texture2D(lightBuffer, vec2(0.625,v));\r\n    light.color = p1.rgb;\r\n\tlight.range=p1.a;\r\n    light.position = p2.rgb;\r\n\tlight.spot = p2.a;\r\n\tlight.direction = p3.rgb;\r\n    return light;\r\n}\r\n\r\n\r\n\r\n// Laya中使用衰减纹理\r\nfloat LayaAttenuation(in vec3 L,in float invLightRadius) {\r\n\tfloat fRatio = clamp(length(L) * invLightRadius,0.0,1.0);\r\n\tfRatio *= fRatio;\r\n\treturn 1.0 / (1.0 + 25.0 * fRatio)* clamp(4.0*(1.0 - fRatio),0.0,1.0); //fade to black as if 4 pixel texture\r\n}\r\n\r\n// Same as Just Cause 2 and Crysis 2 (you can read GPU Pro 1 book for more information)\r\nfloat BasicAttenuation(in vec3 L,in float invLightRadius) {\r\n\tvec3 distance = L * invLightRadius;\r\n\tfloat attenuation = clamp(1.0 - dot(distance, distance),0.0,1.0); // Equals float attenuation = saturate(1.0f - dot(L, L) / (lightRadius *  lightRadius));\r\n\treturn attenuation * attenuation;\r\n}\r\n\r\n// Inspired on http://fools.slindev.com/viewtopic.php?f=11&t=21&view=unread#unread\r\nfloat NaturalAttenuation(in vec3 L,in float invLightRadius) {\r\n\tfloat attenuationFactor = 30.0;\r\n\tvec3 distance = L * invLightRadius;\r\n\tfloat attenuation = dot(distance, distance); // Equals float attenuation = dot(L, L) / (lightRadius *  lightRadius);\r\n\tattenuation = 1.0 / (attenuation * attenuationFactor + 1.0);\r\n\t// Second we move down the function therewith it reaches zero at abscissa 1:\r\n\tattenuationFactor = 1.0 / (attenuationFactor + 1.0); //attenuationFactor contains now the value we have to subtract\r\n\tattenuation = max(attenuation - attenuationFactor, 0.0); // The max fixes a bug.\r\n\t// Finally we expand the equation along the y-axis so that it starts with a function value of 1 again.\r\n\tattenuation /= 1.0 - attenuationFactor;\r\n\treturn attenuation;\r\n}\r\n\r\nvoid LayaAirBlinnPhongLight (in vec3 specColor,in float specColorIntensity,in vec3 normal,in vec3 gloss, in vec3 viewDir,in vec3 lightColor, in vec3 lightVec,out vec3 diffuseColor,out vec3 specularColor) {\r\n\tmediump vec3 h = normalize(viewDir-lightVec);\r\n\tlowp float ln = max (0.0, dot (-lightVec,normal));\r\n\tfloat nh = max (0.0, dot (h,normal));\r\n\tdiffuseColor=lightColor * ln;\r\n\tspecularColor=lightColor *specColor*pow (nh, specColorIntensity*128.0) * gloss;\r\n}\r\n\r\nvoid LayaAirBlinnPhongDiectionLight (in vec3 specColor,in float specColorIntensity,in vec3 normal,in vec3 gloss, in vec3 viewDir, in DirectionLight light,out vec3 diffuseColor,out vec3 specularColor) {\r\n\tvec3 lightVec=normalize(light.direction);\r\n\tLayaAirBlinnPhongLight(specColor,specColorIntensity,normal,gloss,viewDir,light.color,lightVec,diffuseColor,specularColor);\r\n}\r\n\r\nvoid LayaAirBlinnPhongPointLight (in vec3 pos,in vec3 specColor,in float specColorIntensity,in vec3 normal,in vec3 gloss, in vec3 viewDir, in PointLight light,out vec3 diffuseColor,out vec3 specularColor) {\r\n\tvec3 lightVec =  pos-light.position;\r\n\tLayaAirBlinnPhongLight(specColor,specColorIntensity,normal,gloss,viewDir,light.color,lightVec/length(lightVec),diffuseColor,specularColor);\r\n\tfloat attenuate = LayaAttenuation(lightVec, 1.0/light.range);\r\n\tdiffuseColor *= attenuate;\r\n\tspecularColor*= attenuate;\r\n}\r\n\r\nvoid LayaAirBlinnPhongSpotLight (in vec3 pos,in vec3 specColor,in float specColorIntensity,in vec3 normal,in vec3 gloss, in vec3 viewDir, in SpotLight light,out vec3 diffuseColor,out vec3 specularColor) {\r\n\tvec3 lightVec =  pos-light.position;\r\n\tvec3 normalLightVec=lightVec/length(lightVec);\r\n\tLayaAirBlinnPhongLight(specColor,specColorIntensity,normal,gloss,viewDir,light.color,normalLightVec,diffuseColor,specularColor);\r\n\tvec2 cosAngles=cos(vec2(light.spot,light.spot*0.5)*0.5);//ConeAttenuation\r\n\tfloat dl=dot(normalize(light.direction),normalLightVec);\r\n\tdl*=smoothstep(cosAngles[0],cosAngles[1],dl);\r\n\tfloat attenuate = LayaAttenuation(lightVec, 1.0/light.range)*dl;\r\n\tdiffuseColor *=attenuate;\r\n\tspecularColor *=attenuate;\r\n}\r\n\r\nvec3 NormalSampleToWorldSpace(vec3 normalMapSample, vec3 unitNormal, vec3 tangent,vec3 binormal) {\r\n\tvec3 normalT =vec3(2.0*normalMapSample.x - 1.0,1.0-2.0*normalMapSample.y,2.0*normalMapSample.z - 1.0);\r\n\r\n\t// Build orthonormal basis.\r\n\tvec3 N = normalize(unitNormal);\r\n\tvec3 T = normalize(tangent);\r\n\tvec3 B = normalize(binormal);\r\n\tmat3 TBN = mat3(T, B, N);\r\n\r\n\t// Transform from tangent space to world space.\r\n\tvec3 bumpedNormal = TBN*normalT;\r\n\r\n\treturn bumpedNormal;\r\n}\r\n\r\nvec3 NormalSampleToWorldSpace1(vec4 normalMapSample, vec3 tangent, vec3 binormal, vec3 unitNormal) {\r\n\tvec3 normalT;\r\n\tnormalT.x = 2.0 * normalMapSample.x - 1.0;\r\n\tnormalT.y = 1.0 - 2.0 * normalMapSample.y;\r\n\tnormalT.z = sqrt(1.0 - clamp(dot(normalT.xy, normalT.xy), 0.0, 1.0));\r\n\r\n\tvec3 T = normalize(tangent);\r\n\tvec3 B = normalize(binormal);\r\n\tvec3 N = normalize(unitNormal);\r\n\tmat3 TBN = mat3(T, B, N);\r\n\r\n\t// Transform from tangent space to world space.\r\n\tvec3 bumpedNormal = TBN * normalize(normalT);\r\n\r\n\treturn bumpedNormal;\r\n}\r\n\r\nvec3 DecodeLightmap(vec4 color) {\r\n\treturn color.rgb*color.a*5.0;\r\n}\r\n\r\nvec2 TransformUV(vec2 texcoord,vec4 tilingOffset) {\r\n\tvec2 transTexcoord=vec2(texcoord.x,texcoord.y-1.0)*tilingOffset.xy+vec2(tilingOffset.z,-tilingOffset.w);\r\n\ttransTexcoord.y+=1.0;\r\n\treturn transTexcoord;\r\n}\r\n\r\nvec4 remapGLPositionZ(vec4 position) {\r\n\tposition.z=position.z * 2.0 - position.w;\r\n\treturn position;\r\n}\r\n\r\nmat3 inverse(mat3 m) {\r\n  float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2];\r\n  float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2];\r\n  float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2];\r\n\r\n  float b01 = a22 * a11 - a12 * a21;\r\n  float b11 = -a22 * a10 + a12 * a20;\r\n  float b21 = a21 * a10 - a11 * a20;\r\n\r\n  float det = a00 * b01 + a01 * b11 + a02 * b21;\r\n\r\n  return mat3(b01, (-a22 * a01 + a02 * a21), (a12 * a01 - a02 * a11),\r\n              b11, (a22 * a00 - a02 * a20), (-a12 * a00 + a02 * a10),\r\n              b21, (-a21 * a00 + a01 * a20), (a11 * a00 - a01 * a10)) / det;\r\n}\r\n\r\n";

	var linePS = "#ifdef HIGHPRECISION\r\nprecision highp float;\r\n#else\r\nprecision mediump float;\r\n#endif\r\n\r\nvarying vec4 v_Color;\r\nuniform vec4 u_Color;\r\n\r\nvoid main()\r\n{\r\n  gl_FragColor = v_Color * u_Color; \r\n}\r\n\r\n";

	var lineVS = "#include \"Lighting.glsl\";\r\n\r\nattribute vec4 a_Position;\r\nuniform mat4 u_MvpMatrix;\r\nuniform vec4 u_Color;\r\nattribute vec4 a_Color;\r\nvarying vec4 v_Color;\r\n\r\n\r\nvoid main()\r\n{\r\n\tgl_Position = u_MvpMatrix * a_Position;\r\n\tv_Color=a_Color*u_Color;\r\n\tgl_Position=remapGLPositionZ(gl_Position);\r\n}";

	var MeshBlinnPhongPS = "#ifdef HIGHPRECISION\r\n\tprecision highp float;\r\n\tprecision highp int;\r\n#else\r\n\tprecision mediump float;\r\n\tprecision mediump int;\r\n#endif\r\n\r\n#include \"Lighting.glsl\";\r\n\r\nuniform vec4 u_DiffuseColor;\r\n\r\n#if defined(COLOR)&&defined(ENABLEVERTEXCOLOR)\r\n\tvarying vec4 v_Color;\r\n#endif\r\n\r\n#ifdef ALPHATEST\r\n\tuniform float u_AlphaTestValue;\r\n#endif\r\n\r\n#ifdef DIFFUSEMAP\r\n\tuniform sampler2D u_DiffuseTexture;\r\n#endif\r\n\r\n\r\n#if defined(DIFFUSEMAP)||((defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT))&&(defined(SPECULARMAP)||defined(NORMALMAP)))\r\n\tvarying vec2 v_Texcoord0;\r\n#endif\r\n\r\n#ifdef LIGHTMAP\r\n\tvarying vec2 v_LightMapUV;\r\n\tuniform sampler2D u_LightMap;\r\n#endif\r\n\r\n#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)\r\n\tvarying vec3 v_Normal;\r\n\tvarying vec3 v_ViewDir; \r\n\r\n\tuniform vec3 u_MaterialSpecular;\r\n\tuniform float u_Shininess;\r\n\r\n\t#ifdef LEGACYSINGLELIGHTING\r\n\t\t#ifdef DIRECTIONLIGHT\r\n\t\t\tuniform DirectionLight u_DirectionLight;\r\n\t\t#endif\r\n\t\t#ifdef POINTLIGHT\r\n\t\t\tuniform PointLight u_PointLight;\r\n\t\t#endif\r\n\t\t#ifdef SPOTLIGHT\r\n\t\t\tuniform SpotLight u_SpotLight;\r\n\t\t#endif\r\n\t#else\r\n\t\tuniform mat4 u_View;\r\n\t\tuniform vec4 u_ProjectionParams;\r\n\t\tuniform vec4 u_Viewport;\r\n\t\tuniform int u_DirationLightCount;\r\n\t\tuniform sampler2D u_LightBuffer;\r\n\t\tuniform sampler2D u_LightClusterBuffer;\r\n\t#endif\r\n\r\n\t#ifdef SPECULARMAP \r\n\t\tuniform sampler2D u_SpecularTexture;\r\n\t#endif\r\n\t#ifdef NORMALMAP \r\n\t\tuniform sampler2D u_NormalTexture;\r\n\t\tvarying vec3 v_Tangent;\r\n\t\tvarying vec3 v_Binormal;\r\n\t#endif\r\n#endif\r\n\r\n#ifdef FOG\r\n\tuniform float u_FogStart;\r\n\tuniform float u_FogRange;\r\n\tuniform vec3 u_FogColor;\r\n#endif\r\n\r\n\r\nuniform vec3 u_AmbientColor;\r\n\r\n#if defined(POINTLIGHT)||defined(SPOTLIGHT)||defined(RECEIVESHADOW)\r\n\tvarying vec3 v_PositionWorld;\r\n#endif\r\n\r\n#include \"ShadowHelper.glsl\"\r\nvarying float v_posViewZ;\r\n#ifdef RECEIVESHADOW\r\n\t#if defined(SHADOWMAP_PSSM2)||defined(SHADOWMAP_PSSM3)\r\n\t\tuniform mat4 u_lightShadowVP[4];\r\n\t#endif\r\n\t#ifdef SHADOWMAP_PSSM1 \r\n\t\tvarying vec4 v_lightMVPPos;\r\n\t#endif\r\n#endif\r\n\r\nvoid main_castShadow()\r\n{\r\n\t//gl_FragColor=vec4(v_posViewZ,0.0,0.0,1.0);\r\n\tgl_FragColor=packDepth(v_posViewZ);\r\n\t#if defined(DIFFUSEMAP)&&defined(ALPHATEST)\r\n\t\tfloat alpha = texture2D(u_DiffuseTexture,v_Texcoord0).w;\r\n\t\tif( alpha < u_AlphaTestValue )\r\n\t\t{\r\n\t\t\tdiscard;\r\n\t\t}\r\n\t#endif\r\n}\r\nvoid main_normal()\r\n{\r\n\tvec3 globalDiffuse=u_AmbientColor;\r\n\t#ifdef LIGHTMAP\t\r\n\t\tglobalDiffuse += DecodeLightmap(texture2D(u_LightMap, v_LightMapUV));\r\n\t#endif\r\n\t\r\n\t#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)\r\n\t\tvec3 normal;\r\n\t\t#if (defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT))&&defined(NORMALMAP)\r\n\t\t\tvec3 normalMapSample = texture2D(u_NormalTexture, v_Texcoord0).rgb;\r\n\t\t\tnormal = normalize(NormalSampleToWorldSpace(normalMapSample, v_Normal, v_Tangent,v_Binormal));\r\n\t\t#else\r\n\t\t\tnormal = normalize(v_Normal);\r\n\t\t#endif\r\n\t\tvec3 viewDir= normalize(v_ViewDir);\r\n\t#endif\r\n\t\r\n\tvec4 mainColor=u_DiffuseColor;\r\n\t#ifdef DIFFUSEMAP\r\n\t\tvec4 difTexColor=texture2D(u_DiffuseTexture, v_Texcoord0);\r\n\t\tmainColor=mainColor*difTexColor;\r\n\t#endif \r\n\t#if defined(COLOR)&&defined(ENABLEVERTEXCOLOR)\r\n\t\tmainColor=mainColor*v_Color;\r\n\t#endif \r\n    \r\n\t#ifdef ALPHATEST\r\n\t\tif(mainColor.a<u_AlphaTestValue)\r\n\t\t\tdiscard;\r\n\t#endif\r\n  \r\n\t\r\n\tvec3 diffuse = vec3(0.0);\r\n\tvec3 specular= vec3(0.0);\r\n\t#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)\r\n\t\tvec3 dif,spe;\r\n\t\t#ifdef SPECULARMAP\r\n\t\t\tvec3 gloss=texture2D(u_SpecularTexture, v_Texcoord0).rgb;\r\n\t\t#else\r\n\t\t\t#ifdef DIFFUSEMAP\r\n\t\t\t\tvec3 gloss=vec3(difTexColor.a);\r\n\t\t\t#else\r\n\t\t\t\tvec3 gloss=vec3(1.0);\r\n\t\t\t#endif\r\n\t\t#endif\r\n\t#endif\r\n\r\n\t#ifdef LEGACYSINGLELIGHTING\r\n\t\t#ifdef DIRECTIONLIGHT\r\n\t\t\tLayaAirBlinnPhongDiectionLight(u_MaterialSpecular,u_Shininess,normal,gloss,viewDir,u_DirectionLight,dif,spe);\r\n\t\t\tdiffuse+=dif;\r\n\t\t\tspecular+=spe;\r\n\t\t#endif\r\n\t\r\n\t\t#ifdef POINTLIGHT\r\n\t\t\tLayaAirBlinnPhongPointLight(v_PositionWorld,u_MaterialSpecular,u_Shininess,normal,gloss,viewDir,u_PointLight,dif,spe);\r\n\t\t\tdiffuse+=dif;\r\n\t\t\tspecular+=spe;\r\n\t\t#endif\r\n\r\n\t\t#ifdef SPOTLIGHT\r\n\t\t\tLayaAirBlinnPhongSpotLight(v_PositionWorld,u_MaterialSpecular,u_Shininess,normal,gloss,viewDir,u_SpotLight,dif,spe);\r\n\t\t\tdiffuse+=dif;\r\n\t\t\tspecular+=spe;\r\n\t\t#endif\r\n\t#else\r\n\t\t#ifdef DIRECTIONLIGHT\r\n\t\t\tfor (int i = 0; i < MAX_LIGHT_COUNT; i++) \r\n\t\t\t{\r\n\t\t\t\tif(i >= u_DirationLightCount)\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tDirectionLight directionLight = getDirectionLight(u_LightBuffer,i);\r\n\t\t\t\tLayaAirBlinnPhongDiectionLight(u_MaterialSpecular,u_Shininess,normal,gloss,viewDir,directionLight,dif,spe);\r\n\t\t\t\tdiffuse+=dif;\r\n\t\t\t\tspecular+=spe;\r\n\t\t\t}\r\n\t\t#endif\r\n\t\t#if defined(POINTLIGHT)||defined(SPOTLIGHT)\r\n\t\t\tivec4 clusterInfo =getClusterInfo(u_LightClusterBuffer,u_View,u_Viewport, v_PositionWorld,gl_FragCoord,u_ProjectionParams);\r\n\t\t\t#ifdef POINTLIGHT\r\n\t\t\t\tfor (int i = 0; i < MAX_LIGHT_COUNT; i++) \r\n\t\t\t\t{\r\n\t\t\t\t\tif(i >= clusterInfo.x)//PointLightCount\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tPointLight pointLight = getPointLight(u_LightBuffer,u_LightClusterBuffer,clusterInfo,i);\r\n\t\t\t\t\tLayaAirBlinnPhongPointLight(v_PositionWorld,u_MaterialSpecular,u_Shininess,normal,gloss,viewDir,pointLight,dif,spe);\r\n\t\t\t\t\tdiffuse+=dif;\r\n\t\t\t\t\tspecular+=spe;\r\n\t\t\t\t}\r\n\t\t\t#endif\r\n\t\t\t#ifdef SPOTLIGHT\r\n\t\t\t\tfor (int i = 0; i < MAX_LIGHT_COUNT; i++) \r\n\t\t\t\t{\r\n\t\t\t\t\tif(i >= clusterInfo.y)//SpotLightCount\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tSpotLight spotLight = getSpotLight(u_LightBuffer,u_LightClusterBuffer,clusterInfo,i);\r\n\t\t\t\t\tLayaAirBlinnPhongSpotLight(v_PositionWorld,u_MaterialSpecular,u_Shininess,normal,gloss,viewDir,spotLight,dif,spe);\r\n\t\t\t\t\tdiffuse+=dif;\r\n\t\t\t\t\tspecular+=spe;\r\n\t\t\t\t}\r\n\t\t\t#endif\r\n\t\t#endif\r\n\t#endif\r\n\r\n\t#ifdef RECEIVESHADOW\r\n\t\tfloat shadowValue = 1.0;\r\n\t\t#ifdef SHADOWMAP_PSSM3\r\n\t\t\tshadowValue = getShadowPSSM3(u_shadowMap1,u_shadowMap2,u_shadowMap3,u_lightShadowVP,u_shadowPSSMDistance,u_shadowPCFoffset,v_PositionWorld,v_posViewZ,0.001);\r\n\t\t#endif\r\n\t\t#ifdef SHADOWMAP_PSSM2\r\n\t\t\tshadowValue = getShadowPSSM2(u_shadowMap1,u_shadowMap2,u_lightShadowVP,u_shadowPSSMDistance,u_shadowPCFoffset,v_PositionWorld,v_posViewZ,0.001);\r\n\t\t#endif \r\n\t\t#ifdef SHADOWMAP_PSSM1\r\n\t\t\tshadowValue = getShadowPSSM1(u_shadowMap1,v_lightMVPPos,u_shadowPSSMDistance,u_shadowPCFoffset,v_posViewZ,0.001);\r\n\t\t#endif\r\n\t\tgl_FragColor =vec4(mainColor.rgb*(globalDiffuse + diffuse*shadowValue),mainColor.a);\r\n\t#else\r\n\t\tgl_FragColor =vec4(mainColor.rgb*(globalDiffuse + diffuse),mainColor.a);\r\n\t#endif\r\n\r\n\t#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)\r\n\t\t#ifdef RECEIVESHADOW\r\n\t\t\tgl_FragColor.rgb+=specular*shadowValue;\r\n\t\t#else\r\n\t\t\tgl_FragColor.rgb+=specular;\r\n\t\t#endif\r\n\t#endif\r\n\t  \r\n\t#ifdef FOG\r\n\t\tfloat lerpFact=clamp((1.0/gl_FragCoord.w-u_FogStart)/u_FogRange,0.0,1.0);\r\n\t\tgl_FragColor.rgb=mix(gl_FragColor.rgb,u_FogColor,lerpFact);\r\n\t#endif\r\n}\r\n\r\nvoid main()\r\n{\r\n\t#ifdef CASTSHADOW\t\t\r\n\t\tmain_castShadow();\r\n\t#else\r\n\t\tmain_normal();\r\n\t#endif  \r\n}\r\n\r\n";

	var MeshBlinnPhongVS = "#include \"Lighting.glsl\";\r\n\r\nattribute vec4 a_Position;\r\n\r\n#ifdef GPU_INSTANCE\r\n\tattribute mat4 a_MvpMatrix;\r\n#else\r\n\tuniform mat4 u_MvpMatrix;\r\n#endif\r\n\r\n\r\n#if defined(DIFFUSEMAP)||((defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT))&&(defined(SPECULARMAP)||defined(NORMALMAP)))||(defined(LIGHTMAP)&&defined(UV))\r\n\tattribute vec2 a_Texcoord0;\r\n\tvarying vec2 v_Texcoord0;\r\n#endif\r\n\r\n#if defined(LIGHTMAP)&&defined(UV1)\r\n\tattribute vec2 a_Texcoord1;\r\n#endif\r\n\r\n#ifdef LIGHTMAP\r\n\tuniform vec4 u_LightmapScaleOffset;\r\n\tvarying vec2 v_LightMapUV;\r\n#endif\r\n\r\n#ifdef COLOR\r\n\tattribute vec4 a_Color;\r\n\tvarying vec4 v_Color;\r\n#endif\r\n\r\n#ifdef BONE\r\n\tconst int c_MaxBoneCount = 24;\r\n\tattribute vec4 a_BoneIndices;\r\n\tattribute vec4 a_BoneWeights;\r\n\tuniform mat4 u_Bones[c_MaxBoneCount];\r\n#endif\r\n\r\n#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)\r\n\tattribute vec3 a_Normal;\r\n\tvarying vec3 v_Normal; \r\n\tuniform vec3 u_CameraPos;\r\n\tvarying vec3 v_ViewDir; \r\n#endif\r\n\r\n#if (defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT))&&defined(NORMALMAP)\r\n\tattribute vec4 a_Tangent0;\r\n\tvarying vec3 v_Tangent;\r\n\tvarying vec3 v_Binormal;\r\n#endif\r\n\r\n#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)||defined(RECEIVESHADOW)\r\n\t#ifdef GPU_INSTANCE\r\n\t\tattribute mat4 a_WorldMat;\r\n\t#else\r\n\t\tuniform mat4 u_WorldMat;\r\n\t#endif\r\n\tvarying vec3 v_PositionWorld;\r\n#endif\r\n\r\nvarying float v_posViewZ;\r\n#ifdef RECEIVESHADOW\r\n  #ifdef SHADOWMAP_PSSM1 \r\n  varying vec4 v_lightMVPPos;\r\n  uniform mat4 u_lightShadowVP[4];\r\n  #endif\r\n#endif\r\n\r\n#ifdef TILINGOFFSET\r\n\tuniform vec4 u_TilingOffset;\r\n#endif\r\n\r\nvoid main_castShadow()\r\n{\r\n\tvec4 position;\r\n\t#ifdef BONE\r\n\t\tmat4 skinTransform = u_Bones[int(a_BoneIndices.x)] * a_BoneWeights.x;\r\n\t\tskinTransform += u_Bones[int(a_BoneIndices.y)] * a_BoneWeights.y;\r\n\t\tskinTransform += u_Bones[int(a_BoneIndices.z)] * a_BoneWeights.z;\r\n\t\tskinTransform += u_Bones[int(a_BoneIndices.w)] * a_BoneWeights.w;\r\n\t\tposition=skinTransform*a_Position;\r\n\t#else\r\n\t\tposition=a_Position;\r\n\t#endif\r\n\t#ifdef GPU_INSTANCE\r\n\t\tgl_Position = a_MvpMatrix * position;\r\n\t#else\r\n\t\tgl_Position = u_MvpMatrix * position;\r\n\t#endif\r\n\t\r\n\t//TODO没考虑UV动画呢\r\n\t#if defined(DIFFUSEMAP)&&defined(ALPHATEST)\r\n\t\tv_Texcoord0=a_Texcoord0;\r\n\t#endif\r\n\tgl_Position=remapGLPositionZ(gl_Position);\r\n\tv_posViewZ = gl_Position.z;\r\n}\r\n\r\nvoid main_normal()\r\n{\r\n\tvec4 position;\r\n\t#ifdef BONE\r\n\t\tmat4 skinTransform = u_Bones[int(a_BoneIndices.x)] * a_BoneWeights.x;\r\n\t\tskinTransform += u_Bones[int(a_BoneIndices.y)] * a_BoneWeights.y;\r\n\t\tskinTransform += u_Bones[int(a_BoneIndices.z)] * a_BoneWeights.z;\r\n\t\tskinTransform += u_Bones[int(a_BoneIndices.w)] * a_BoneWeights.w;\r\n\t\tposition=skinTransform*a_Position;\r\n\t#else\r\n\t\tposition=a_Position;\r\n\t#endif\r\n\t#ifdef GPU_INSTANCE\r\n\t\tgl_Position = a_MvpMatrix * position;\r\n\t#else\r\n\t\tgl_Position = u_MvpMatrix * position;\r\n\t#endif\r\n\t\r\n\t#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)||defined(RECEIVESHADOW)\r\n\t\tmat4 worldMat;\r\n\t\t#ifdef GPU_INSTANCE\r\n\t\t\tworldMat = a_WorldMat;\r\n\t\t#else\r\n\t\t\tworldMat = u_WorldMat;\r\n\t\t#endif\r\n\t#endif\r\n\t\r\n\r\n\t#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)\r\n\t\tmat3 worldInvMat;\r\n\t\t#ifdef BONE\r\n\t\t\tworldInvMat=inverse(mat3(worldMat*skinTransform));\r\n\t\t#else\r\n\t\t\tworldInvMat=inverse(mat3(worldMat));\r\n\t\t#endif  \r\n\t\tv_Normal=a_Normal*worldInvMat;\r\n\t\t#if (defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT))&&defined(NORMALMAP)\r\n\t\t\tv_Tangent=a_Tangent0.xyz*worldInvMat;\r\n\t\t\tv_Binormal=cross(v_Normal,v_Tangent)*a_Tangent0.w;\r\n\t\t#endif\r\n\t#endif\r\n\r\n\t#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)||defined(RECEIVESHADOW)\r\n\t\tv_PositionWorld=(worldMat*position).xyz;\r\n\t#endif\r\n\t\r\n\t#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)\r\n\t\tv_ViewDir=u_CameraPos-v_PositionWorld;\r\n\t#endif\r\n\r\n\t#if defined(DIFFUSEMAP)||((defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT))&&(defined(SPECULARMAP)||defined(NORMALMAP)))\r\n\t\t#ifdef TILINGOFFSET\r\n\t\t\tv_Texcoord0=TransformUV(a_Texcoord0,u_TilingOffset);\r\n\t\t#else\r\n\t\t\tv_Texcoord0=a_Texcoord0;\r\n\t\t#endif\r\n\t#endif\r\n\r\n\t#ifdef LIGHTMAP\r\n\t\t#ifdef SCALEOFFSETLIGHTINGMAPUV\r\n\t\t\t#ifdef UV1\r\n\t\t\t\tv_LightMapUV=vec2(a_Texcoord1.x,1.0-a_Texcoord1.y)*u_LightmapScaleOffset.xy+u_LightmapScaleOffset.zw;\r\n\t\t\t#else\r\n\t\t\t\tv_LightMapUV=vec2(a_Texcoord0.x,1.0-a_Texcoord0.y)*u_LightmapScaleOffset.xy+u_LightmapScaleOffset.zw;\r\n\t\t\t#endif \r\n\t\t\tv_LightMapUV.y=1.0-v_LightMapUV.y;\r\n\t\t#else\r\n\t\t\t#ifdef UV1\r\n\t\t\t\tv_LightMapUV=a_Texcoord1;\r\n\t\t\t#else\r\n\t\t\t\tv_LightMapUV=a_Texcoord0;\r\n\t\t\t#endif \r\n\t\t#endif \r\n\t#endif\r\n\r\n\t#if defined(COLOR)&&defined(ENABLEVERTEXCOLOR)\r\n\t\tv_Color=a_Color;\r\n\t#endif\r\n\r\n\t#ifdef RECEIVESHADOW\r\n\t\tv_posViewZ = gl_Position.w;\r\n\t\t#ifdef SHADOWMAP_PSSM1 \r\n\t\t\tv_lightMVPPos = u_lightShadowVP[0] * vec4(v_PositionWorld,1.0);\r\n\t\t#endif\r\n\t#endif\r\n\tgl_Position=remapGLPositionZ(gl_Position);\r\n}\r\n\r\nvoid main()\r\n{\r\n\t#ifdef CASTSHADOW\r\n\t\tmain_castShadow();\r\n\t#else\r\n\t\tmain_normal();\r\n\t#endif\r\n}";

	var ParticleShuriKenPS = "#ifdef HIGHPRECISION\r\n  precision highp float;\r\n#else\r\n  precision mediump float;\r\n#endif\r\n\r\nvarying vec4 v_Color;\r\nvarying vec2 v_TextureCoordinate;\r\nuniform sampler2D u_texture;\r\nuniform vec4 u_Tintcolor;\r\n\r\n#ifdef RENDERMODE_MESH\r\n\tvarying vec4 v_MeshColor;\r\n#endif\r\n\r\n#ifdef FOG\r\n\tuniform float u_FogStart;\r\n\tuniform float u_FogRange;\r\n\t#ifdef ADDTIVEFOG\r\n\t#else\r\n\t\tuniform vec3 u_FogColor;\r\n\t#endif\r\n#endif\r\n\r\n\r\nvoid main()\r\n{\t\r\n\t#ifdef RENDERMODE_MESH\r\n\t\tgl_FragColor=v_MeshColor;\r\n\t#else\r\n\t\tgl_FragColor=vec4(1.0);\t\r\n\t#endif\r\n\t\t\r\n\t#ifdef DIFFUSEMAP\r\n\t\t#ifdef TINTCOLOR\r\n\t\t\tgl_FragColor*=texture2D(u_texture,v_TextureCoordinate)*u_Tintcolor*2.0*v_Color;\r\n\t\t#else\r\n\t\t\tgl_FragColor*=texture2D(u_texture,v_TextureCoordinate)*v_Color;\r\n\t\t#endif\r\n\t#else\r\n\t\t#ifdef TINTCOLOR\r\n\t\t\tgl_FragColor*=u_Tintcolor*2.0*v_Color;\r\n\t\t#else\r\n\t\t\tgl_FragColor*=v_Color;\r\n\t\t#endif\r\n\t#endif\r\n\t\r\n\t#ifdef FOG\r\n\t\tfloat lerpFact=clamp((1.0/gl_FragCoord.w-u_FogStart)/u_FogRange,0.0,1.0);\r\n\t\t#ifdef ADDTIVEFOG\r\n\t\t\tgl_FragColor.rgb=mix(gl_FragColor.rgb,vec3(0.0,0.0,0.0),lerpFact);\r\n\t\t#else\r\n\t\t\tgl_FragColor.rgb=mix(gl_FragColor.rgb,u_FogColor,lerpFact);\r\n\t\t#endif\r\n\t#endif\r\n}";

	var ParticleShuriKenVS = "#include \"Lighting.glsl\";\r\n\r\n#ifdef HIGHPRECISION\r\n  precision highp float;\r\n#else\r\n  precision mediump float;\r\n#endif\r\n\r\n#if defined(SPHERHBILLBOARD)||defined(STRETCHEDBILLBOARD)||defined(HORIZONTALBILLBOARD)||defined(VERTICALBILLBOARD)\r\n\tattribute vec4 a_CornerTextureCoordinate;\r\n#endif\r\n#ifdef RENDERMODE_MESH\r\n\tattribute vec3 a_MeshPosition;\r\n\tattribute vec4 a_MeshColor;\r\n\tattribute vec2 a_MeshTextureCoordinate;\r\n\tvarying vec4 v_MeshColor;\r\n#endif\r\n\r\nattribute vec4 a_ShapePositionStartLifeTime;\r\nattribute vec4 a_DirectionTime;\r\nattribute vec4 a_StartColor;\r\nattribute vec3 a_StartSize;\r\nattribute vec3 a_StartRotation0;\r\nattribute float a_StartSpeed;\r\n#if defined(COLOROVERLIFETIME)||defined(RANDOMCOLOROVERLIFETIME)||defined(SIZEOVERLIFETIMERANDOMCURVES)||defined(SIZEOVERLIFETIMERANDOMCURVESSEPERATE)||defined(ROTATIONOVERLIFETIMERANDOMCONSTANTS)||defined(ROTATIONOVERLIFETIMERANDOMCURVES)\r\n  attribute vec4 a_Random0;\r\n#endif\r\n#if defined(TEXTURESHEETANIMATIONRANDOMCURVE)||defined(VELOCITYOVERLIFETIMERANDOMCONSTANT)||defined(VELOCITYOVERLIFETIMERANDOMCURVE)\r\n  attribute vec4 a_Random1;\r\n#endif\r\nattribute vec3 a_SimulationWorldPostion;\r\nattribute vec4 a_SimulationWorldRotation;\r\n\r\nvarying vec4 v_Color;\r\n#ifdef DIFFUSEMAP\r\n\tvarying vec2 v_TextureCoordinate;\r\n#endif\r\n\r\nuniform float u_CurrentTime;\r\nuniform vec3 u_Gravity;\r\n\r\nuniform vec3 u_WorldPosition;\r\nuniform vec4 u_WorldRotation;\r\nuniform bool u_ThreeDStartRotation;\r\nuniform int u_ScalingMode;\r\nuniform vec3 u_PositionScale;\r\nuniform vec3 u_SizeScale;\r\nuniform mat4 u_View;\r\nuniform mat4 u_Projection;\r\n\r\n#ifdef STRETCHEDBILLBOARD\r\n\tuniform vec3 u_CameraPos;\r\n#endif\r\nuniform vec3 u_CameraDirection;//TODO:只有几种广告牌模式需要用\r\nuniform vec3 u_CameraUp;\r\n\r\nuniform  float u_StretchedBillboardLengthScale;\r\nuniform  float u_StretchedBillboardSpeedScale;\r\nuniform int u_SimulationSpace;\r\n\r\n#if defined(VELOCITYOVERLIFETIMECONSTANT)||defined(VELOCITYOVERLIFETIMECURVE)||defined(VELOCITYOVERLIFETIMERANDOMCONSTANT)||defined(VELOCITYOVERLIFETIMERANDOMCURVE)\r\n  uniform  int  u_VOLSpaceType;\r\n#endif\r\n#if defined(VELOCITYOVERLIFETIMECONSTANT)||defined(VELOCITYOVERLIFETIMERANDOMCONSTANT)\r\n  uniform  vec3 u_VOLVelocityConst;\r\n#endif\r\n#if defined(VELOCITYOVERLIFETIMECURVE)||defined(VELOCITYOVERLIFETIMERANDOMCURVE)\r\n  uniform  vec2 u_VOLVelocityGradientX[4];//x为key,y为速度\r\n  uniform  vec2 u_VOLVelocityGradientY[4];//x为key,y为速度\r\n  uniform  vec2 u_VOLVelocityGradientZ[4];//x为key,y为速度\r\n#endif\r\n#ifdef VELOCITYOVERLIFETIMERANDOMCONSTANT\r\n  uniform  vec3 u_VOLVelocityConstMax;\r\n#endif\r\n#ifdef VELOCITYOVERLIFETIMERANDOMCURVE\r\n  uniform  vec2 u_VOLVelocityGradientMaxX[4];//x为key,y为速度\r\n  uniform  vec2 u_VOLVelocityGradientMaxY[4];//x为key,y为速度\r\n  uniform  vec2 u_VOLVelocityGradientMaxZ[4];//x为key,y为速度\r\n#endif\r\n\r\n#ifdef COLOROVERLIFETIME\r\n  uniform  vec4 u_ColorOverLifeGradientColors[4];//x为key,yzw为Color\r\n  uniform  vec2 u_ColorOverLifeGradientAlphas[4];//x为key,y为Alpha\r\n#endif\r\n#ifdef RANDOMCOLOROVERLIFETIME\r\n  uniform  vec4 u_ColorOverLifeGradientColors[4];//x为key,yzw为Color\r\n  uniform  vec2 u_ColorOverLifeGradientAlphas[4];//x为key,y为Alpha\r\n  uniform  vec4 u_MaxColorOverLifeGradientColors[4];//x为key,yzw为Color\r\n  uniform  vec2 u_MaxColorOverLifeGradientAlphas[4];//x为key,y为Alpha\r\n#endif\r\n\r\n\r\n#if defined(SIZEOVERLIFETIMECURVE)||defined(SIZEOVERLIFETIMERANDOMCURVES)\r\n  uniform  vec2 u_SOLSizeGradient[4];//x为key,y为尺寸\r\n#endif\r\n#ifdef SIZEOVERLIFETIMERANDOMCURVES\r\n  uniform  vec2 u_SOLSizeGradientMax[4];//x为key,y为尺寸\r\n#endif\r\n#if defined(SIZEOVERLIFETIMECURVESEPERATE)||defined(SIZEOVERLIFETIMERANDOMCURVESSEPERATE)\r\n  uniform  vec2 u_SOLSizeGradientX[4];//x为key,y为尺寸\r\n  uniform  vec2 u_SOLSizeGradientY[4];//x为key,y为尺寸\r\n  uniform  vec2 u_SOLSizeGradientZ[4];//x为key,y为尺寸\r\n#endif\r\n#ifdef SIZEOVERLIFETIMERANDOMCURVESSEPERATE\r\n  uniform  vec2 u_SOLSizeGradientMaxX[4];//x为key,y为尺寸\r\n  uniform  vec2 u_SOLSizeGradientMaxY[4];//x为key,y为尺寸\r\n  uniform  vec2 u_SOLSizeGradientMaxZ[4];//x为key,y为尺寸\r\n#endif\r\n\r\n\r\n#ifdef ROTATIONOVERLIFETIME\r\n  #if defined(ROTATIONOVERLIFETIMECONSTANT)||defined(ROTATIONOVERLIFETIMERANDOMCONSTANTS)\r\n    uniform  float u_ROLAngularVelocityConst;\r\n  #endif\r\n  #ifdef ROTATIONOVERLIFETIMERANDOMCONSTANTS\r\n    uniform  float u_ROLAngularVelocityConstMax;\r\n  #endif\r\n  #if defined(ROTATIONOVERLIFETIMECURVE)||defined(ROTATIONOVERLIFETIMERANDOMCURVES)\r\n    uniform  vec2 u_ROLAngularVelocityGradient[4];//x为key,y为旋转\r\n  #endif\r\n  #ifdef ROTATIONOVERLIFETIMERANDOMCURVES\r\n    uniform  vec2 u_ROLAngularVelocityGradientMax[4];//x为key,y为旋转\r\n  #endif\r\n#endif\r\n#ifdef ROTATIONOVERLIFETIMESEPERATE\r\n  #if defined(ROTATIONOVERLIFETIMECONSTANT)||defined(ROTATIONOVERLIFETIMERANDOMCONSTANTS)\r\n    uniform  vec3 u_ROLAngularVelocityConstSeprarate;\r\n  #endif\r\n  #ifdef ROTATIONOVERLIFETIMERANDOMCONSTANTS\r\n    uniform  vec3 u_ROLAngularVelocityConstMaxSeprarate;\r\n  #endif\r\n  #if defined(ROTATIONOVERLIFETIMECURVE)||defined(ROTATIONOVERLIFETIMERANDOMCURVES)\r\n    uniform  vec2 u_ROLAngularVelocityGradientX[4];\r\n    uniform  vec2 u_ROLAngularVelocityGradientY[4];\r\n    uniform  vec2 u_ROLAngularVelocityGradientZ[4];\r\n  #endif\r\n  #ifdef ROTATIONOVERLIFETIMERANDOMCURVES\r\n    uniform  vec2 u_ROLAngularVelocityGradientMaxX[4];\r\n    uniform  vec2 u_ROLAngularVelocityGradientMaxY[4];\r\n    uniform  vec2 u_ROLAngularVelocityGradientMaxZ[4];\r\n\tuniform  vec2 u_ROLAngularVelocityGradientMaxW[4];\r\n  #endif\r\n#endif\r\n\r\n#if defined(TEXTURESHEETANIMATIONCURVE)||defined(TEXTURESHEETANIMATIONRANDOMCURVE)\r\n  uniform  float u_TSACycles;\r\n  uniform  vec2 u_TSASubUVLength;\r\n  uniform  vec2 u_TSAGradientUVs[4];//x为key,y为frame\r\n#endif\r\n#ifdef TEXTURESHEETANIMATIONRANDOMCURVE\r\n  uniform  vec2 u_TSAMaxGradientUVs[4];//x为key,y为frame\r\n#endif\r\n\r\n#ifdef TILINGOFFSET\r\n\tuniform vec4 u_TilingOffset;\r\n#endif\r\n\r\nvec3 rotationByEuler(in vec3 vector,in vec3 rot)\r\n{\r\n\tfloat halfRoll = rot.z * 0.5;\r\n    float halfPitch = rot.x * 0.5;\r\n\tfloat halfYaw = rot.y * 0.5;\r\n\r\n\tfloat sinRoll = sin(halfRoll);\r\n\tfloat cosRoll = cos(halfRoll);\r\n\tfloat sinPitch = sin(halfPitch);\r\n\tfloat cosPitch = cos(halfPitch);\r\n\tfloat sinYaw = sin(halfYaw);\r\n\tfloat cosYaw = cos(halfYaw);\r\n\r\n\tfloat quaX = (cosYaw * sinPitch * cosRoll) + (sinYaw * cosPitch * sinRoll);\r\n\tfloat quaY = (sinYaw * cosPitch * cosRoll) - (cosYaw * sinPitch * sinRoll);\r\n\tfloat quaZ = (cosYaw * cosPitch * sinRoll) - (sinYaw * sinPitch * cosRoll);\r\n\tfloat quaW = (cosYaw * cosPitch * cosRoll) + (sinYaw * sinPitch * sinRoll);\r\n\t\r\n\t//vec4 q=vec4(quaX,quaY,quaZ,quaW);\r\n\t//vec3 temp = cross(q.xyz, vector) + q.w * vector;\r\n\t//return (cross(temp, -q.xyz) + dot(q.xyz,vector) * q.xyz + q.w * temp);\r\n\t\r\n\tfloat x = quaX + quaX;\r\n    float y = quaY + quaY;\r\n    float z = quaZ + quaZ;\r\n    float wx = quaW * x;\r\n    float wy = quaW * y;\r\n    float wz = quaW * z;\r\n\tfloat xx = quaX * x;\r\n    float xy = quaX * y;\r\n\tfloat xz = quaX * z;\r\n    float yy = quaY * y;\r\n    float yz = quaY * z;\r\n    float zz = quaZ * z;\r\n\r\n    return vec3(((vector.x * ((1.0 - yy) - zz)) + (vector.y * (xy - wz))) + (vector.z * (xz + wy)),\r\n                ((vector.x * (xy + wz)) + (vector.y * ((1.0 - xx) - zz))) + (vector.z * (yz - wx)),\r\n                ((vector.x * (xz - wy)) + (vector.y * (yz + wx))) + (vector.z * ((1.0 - xx) - yy)));\r\n\t\r\n}\r\n\r\n//假定axis已经归一化\r\nvec3 rotationByAxis(in vec3 vector,in vec3 axis, in float angle)\r\n{\r\n\tfloat halfAngle = angle * 0.5;\r\n\tfloat sin = sin(halfAngle);\r\n\t\r\n\tfloat quaX = axis.x * sin;\r\n\tfloat quaY = axis.y * sin;\r\n\tfloat quaZ = axis.z * sin;\r\n\tfloat quaW = cos(halfAngle);\r\n\t\r\n\t//vec4 q=vec4(quaX,quaY,quaZ,quaW);\r\n\t//vec3 temp = cross(q.xyz, vector) + q.w * vector;\r\n\t//return (cross(temp, -q.xyz) + dot(q.xyz,vector) * q.xyz + q.w * temp);\r\n\t\r\n\tfloat x = quaX + quaX;\r\n    float y = quaY + quaY;\r\n    float z = quaZ + quaZ;\r\n    float wx = quaW * x;\r\n    float wy = quaW * y;\r\n    float wz = quaW * z;\r\n\tfloat xx = quaX * x;\r\n    float xy = quaX * y;\r\n\tfloat xz = quaX * z;\r\n    float yy = quaY * y;\r\n    float yz = quaY * z;\r\n    float zz = quaZ * z;\r\n\r\n    return vec3(((vector.x * ((1.0 - yy) - zz)) + (vector.y * (xy - wz))) + (vector.z * (xz + wy)),\r\n                ((vector.x * (xy + wz)) + (vector.y * ((1.0 - xx) - zz))) + (vector.z * (yz - wx)),\r\n                ((vector.x * (xz - wy)) + (vector.y * (yz + wx))) + (vector.z * ((1.0 - xx) - yy)));\r\n\t\r\n}\r\n\r\nvec3 rotationByQuaternions(in vec3 v,in vec4 q) \r\n{\r\n\treturn v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);\r\n}\r\n\r\n \r\n#if defined(VELOCITYOVERLIFETIMECURVE)||defined(VELOCITYOVERLIFETIMERANDOMCURVE)||defined(SIZEOVERLIFETIMECURVE)||defined(SIZEOVERLIFETIMECURVESEPERATE)||defined(SIZEOVERLIFETIMERANDOMCURVES)||defined(SIZEOVERLIFETIMERANDOMCURVESSEPERATE)\r\nfloat getCurValueFromGradientFloat(in vec2 gradientNumbers[4],in float normalizedAge)\r\n{\r\n\tfloat curValue;\r\n\tfor(int i=1;i<4;i++)\r\n\t{\r\n\t\tvec2 gradientNumber=gradientNumbers[i];\r\n\t\tfloat key=gradientNumber.x;\r\n\t\tif(key>=normalizedAge)\r\n\t\t{\r\n\t\t\tvec2 lastGradientNumber=gradientNumbers[i-1];\r\n\t\t\tfloat lastKey=lastGradientNumber.x;\r\n\t\t\tfloat age=(normalizedAge-lastKey)/(key-lastKey);\r\n\t\t\tcurValue=mix(lastGradientNumber.y,gradientNumber.y,age);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\treturn curValue;\r\n}\r\n#endif\r\n\r\n#if defined(VELOCITYOVERLIFETIMECURVE)||defined(VELOCITYOVERLIFETIMERANDOMCURVE)||defined(ROTATIONOVERLIFETIMECURVE)||defined(ROTATIONOVERLIFETIMERANDOMCURVES)\r\nfloat getTotalValueFromGradientFloat(in vec2 gradientNumbers[4],in float normalizedAge)\r\n{\r\n\tfloat totalValue=0.0;\r\n\tfor(int i=1;i<4;i++)\r\n\t{\r\n\t\tvec2 gradientNumber=gradientNumbers[i];\r\n\t\tfloat key=gradientNumber.x;\r\n\t\tvec2 lastGradientNumber=gradientNumbers[i-1];\r\n\t\tfloat lastValue=lastGradientNumber.y;\r\n\t\t\r\n\t\tif(key>=normalizedAge){\r\n\t\t\tfloat lastKey=lastGradientNumber.x;\r\n\t\t\tfloat age=(normalizedAge-lastKey)/(key-lastKey);\r\n\t\t\ttotalValue+=(lastValue+mix(lastValue,gradientNumber.y,age))/2.0*a_ShapePositionStartLifeTime.w*(normalizedAge-lastKey);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\telse{\r\n\t\t\ttotalValue+=(lastValue+gradientNumber.y)/2.0*a_ShapePositionStartLifeTime.w*(key-lastGradientNumber.x);\r\n\t\t}\r\n\t}\r\n\treturn totalValue;\r\n}\r\n#endif\r\n\r\n#if defined(COLOROVERLIFETIME)||defined(RANDOMCOLOROVERLIFETIME)\r\nvec4 getColorFromGradient(in vec2 gradientAlphas[4],in vec4 gradientColors[4],in float normalizedAge)\r\n{\r\n\tvec4 overTimeColor;\r\n\tfor(int i=1;i<4;i++)\r\n\t{\r\n\t\tvec2 gradientAlpha=gradientAlphas[i];\r\n\t\tfloat alphaKey=gradientAlpha.x;\r\n\t\tif(alphaKey>=normalizedAge)\r\n\t\t{\r\n\t\t\tvec2 lastGradientAlpha=gradientAlphas[i-1];\r\n\t\t\tfloat lastAlphaKey=lastGradientAlpha.x;\r\n\t\t\tfloat age=(normalizedAge-lastAlphaKey)/(alphaKey-lastAlphaKey);\r\n\t\t\toverTimeColor.a=mix(lastGradientAlpha.y,gradientAlpha.y,age);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\t\r\n\tfor(int i=1;i<4;i++)\r\n\t{\r\n\t\tvec4 gradientColor=gradientColors[i];\r\n\t\tfloat colorKey=gradientColor.x;\r\n\t\tif(colorKey>=normalizedAge)\r\n\t\t{\r\n\t\t\tvec4 lastGradientColor=gradientColors[i-1];\r\n\t\t\tfloat lastColorKey=lastGradientColor.x;\r\n\t\t\tfloat age=(normalizedAge-lastColorKey)/(colorKey-lastColorKey);\r\n\t\t\toverTimeColor.rgb=mix(gradientColors[i-1].yzw,gradientColor.yzw,age);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\treturn overTimeColor;\r\n}\r\n#endif\r\n\r\n\r\n#if defined(TEXTURESHEETANIMATIONCURVE)||defined(TEXTURESHEETANIMATIONRANDOMCURVE)\r\nfloat getFrameFromGradient(in vec2 gradientFrames[4],in float normalizedAge)\r\n{\r\n\tfloat overTimeFrame;\r\n\tfor(int i=1;i<4;i++)\r\n\t{\r\n\t\tvec2 gradientFrame=gradientFrames[i];\r\n\t\tfloat key=gradientFrame.x;\r\n\t\tif(key>=normalizedAge)\r\n\t\t{\r\n\t\t\tvec2 lastGradientFrame=gradientFrames[i-1];\r\n\t\t\tfloat lastKey=lastGradientFrame.x;\r\n\t\t\tfloat age=(normalizedAge-lastKey)/(key-lastKey);\r\n\t\t\toverTimeFrame=mix(lastGradientFrame.y,gradientFrame.y,age);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\treturn floor(overTimeFrame);\r\n}\r\n#endif\r\n\r\n#if defined(VELOCITYOVERLIFETIMECONSTANT)||defined(VELOCITYOVERLIFETIMECURVE)||defined(VELOCITYOVERLIFETIMERANDOMCONSTANT)||defined(VELOCITYOVERLIFETIMERANDOMCURVE)\r\nvec3 computeParticleLifeVelocity(in float normalizedAge)\r\n{\r\n  vec3 outLifeVelocity;\r\n  #ifdef VELOCITYOVERLIFETIMECONSTANT\r\n\t outLifeVelocity=u_VOLVelocityConst; \r\n  #endif\r\n  #ifdef VELOCITYOVERLIFETIMECURVE\r\n     outLifeVelocity= vec3(getCurValueFromGradientFloat(u_VOLVelocityGradientX,normalizedAge),getCurValueFromGradientFloat(u_VOLVelocityGradientY,normalizedAge),getCurValueFromGradientFloat(u_VOLVelocityGradientZ,normalizedAge));\r\n  #endif\r\n  #ifdef VELOCITYOVERLIFETIMERANDOMCONSTANT\r\n\t outLifeVelocity=mix(u_VOLVelocityConst,u_VOLVelocityConstMax,vec3(a_Random1.y,a_Random1.z,a_Random1.w)); \r\n  #endif\r\n  #ifdef VELOCITYOVERLIFETIMERANDOMCURVE\r\n     outLifeVelocity=vec3(mix(getCurValueFromGradientFloat(u_VOLVelocityGradientX,normalizedAge),getCurValueFromGradientFloat(u_VOLVelocityGradientMaxX,normalizedAge),a_Random1.y),\r\n\t                 mix(getCurValueFromGradientFloat(u_VOLVelocityGradientY,normalizedAge),getCurValueFromGradientFloat(u_VOLVelocityGradientMaxY,normalizedAge),a_Random1.z),\r\n\t\t\t\t\t mix(getCurValueFromGradientFloat(u_VOLVelocityGradientZ,normalizedAge),getCurValueFromGradientFloat(u_VOLVelocityGradientMaxZ,normalizedAge),a_Random1.w));\r\n  #endif\r\n\t\t\t\t\t\r\n  return outLifeVelocity;\r\n} \r\n#endif\r\n\r\nvec3 computeParticlePosition(in vec3 startVelocity, in vec3 lifeVelocity,in float age,in float normalizedAge,vec3 gravityVelocity,vec4 worldRotation)\r\n{\r\n   vec3 startPosition;\r\n   vec3 lifePosition;\r\n   #if defined(VELOCITYOVERLIFETIMECONSTANT)||defined(VELOCITYOVERLIFETIMECURVE)||defined(VELOCITYOVERLIFETIMERANDOMCONSTANT)||defined(VELOCITYOVERLIFETIMERANDOMCURVE)\r\n\t#ifdef VELOCITYOVERLIFETIMECONSTANT\r\n\t\t  startPosition=startVelocity*age;\r\n\t\t  lifePosition=lifeVelocity*age;\r\n\t#endif\r\n\t#ifdef VELOCITYOVERLIFETIMECURVE\r\n\t\t  startPosition=startVelocity*age;\r\n\t\t  lifePosition=vec3(getTotalValueFromGradientFloat(u_VOLVelocityGradientX,normalizedAge),getTotalValueFromGradientFloat(u_VOLVelocityGradientY,normalizedAge),getTotalValueFromGradientFloat(u_VOLVelocityGradientZ,normalizedAge));\r\n\t#endif\r\n\t#ifdef VELOCITYOVERLIFETIMERANDOMCONSTANT\r\n\t\t  startPosition=startVelocity*age;\r\n\t\t  lifePosition=lifeVelocity*age;\r\n\t#endif\r\n\t#ifdef VELOCITYOVERLIFETIMERANDOMCURVE\r\n\t\t  startPosition=startVelocity*age;\r\n\t\t  lifePosition=vec3(mix(getTotalValueFromGradientFloat(u_VOLVelocityGradientX,normalizedAge),getTotalValueFromGradientFloat(u_VOLVelocityGradientMaxX,normalizedAge),a_Random1.y)\r\n\t      ,mix(getTotalValueFromGradientFloat(u_VOLVelocityGradientY,normalizedAge),getTotalValueFromGradientFloat(u_VOLVelocityGradientMaxY,normalizedAge),a_Random1.z)\r\n\t      ,mix(getTotalValueFromGradientFloat(u_VOLVelocityGradientZ,normalizedAge),getTotalValueFromGradientFloat(u_VOLVelocityGradientMaxZ,normalizedAge),a_Random1.w));\r\n\t#endif\r\n\t\r\n\tvec3 finalPosition;\r\n\tif(u_VOLSpaceType==0){\r\n\t  if(u_ScalingMode!=2)\r\n\t   finalPosition =rotationByQuaternions(u_PositionScale*(a_ShapePositionStartLifeTime.xyz+startPosition+lifePosition),worldRotation);\r\n\t  else\r\n\t   finalPosition =rotationByQuaternions(u_PositionScale*a_ShapePositionStartLifeTime.xyz+startPosition+lifePosition,worldRotation);\r\n\t}\r\n\telse{\r\n\t  if(u_ScalingMode!=2)\r\n\t    finalPosition = rotationByQuaternions(u_PositionScale*(a_ShapePositionStartLifeTime.xyz+startPosition),worldRotation)+lifePosition;\r\n\t  else\r\n\t    finalPosition = rotationByQuaternions(u_PositionScale*a_ShapePositionStartLifeTime.xyz+startPosition,worldRotation)+lifePosition;\r\n\t}\r\n  #else\r\n\t startPosition=startVelocity*age;\r\n\t vec3 finalPosition;\r\n\t if(u_ScalingMode!=2)\r\n\t\t\tfinalPosition = rotationByQuaternions(u_PositionScale*(a_ShapePositionStartLifeTime.xyz+startPosition),worldRotation);\r\n\t else\r\n\t   \tfinalPosition = rotationByQuaternions(u_PositionScale*a_ShapePositionStartLifeTime.xyz+startPosition,worldRotation);\r\n  #endif\r\n  \r\n  if(u_SimulationSpace==0)\r\n    finalPosition=finalPosition+a_SimulationWorldPostion;\r\n  else if(u_SimulationSpace==1) \r\n    finalPosition=finalPosition+u_WorldPosition;\r\n  \r\n  finalPosition+=0.5*gravityVelocity*age;\r\n \r\n  return  finalPosition;\r\n}\r\n\r\n\r\nvec4 computeParticleColor(in vec4 color,in float normalizedAge)\r\n{\r\n\t#ifdef COLOROVERLIFETIME\r\n\t  color*=getColorFromGradient(u_ColorOverLifeGradientAlphas,u_ColorOverLifeGradientColors,normalizedAge);\r\n\t#endif\r\n\t\r\n\t#ifdef RANDOMCOLOROVERLIFETIME\r\n\t  color*=mix(getColorFromGradient(u_ColorOverLifeGradientAlphas,u_ColorOverLifeGradientColors,normalizedAge),getColorFromGradient(u_MaxColorOverLifeGradientAlphas,u_MaxColorOverLifeGradientColors,normalizedAge),a_Random0.y);\r\n\t#endif\r\n\r\n    return color;\r\n}\r\n\r\nvec2 computeParticleSizeBillbard(in vec2 size,in float normalizedAge)\r\n{\r\n\t#ifdef SIZEOVERLIFETIMECURVE\r\n\t\tsize*=getCurValueFromGradientFloat(u_SOLSizeGradient,normalizedAge);\r\n\t#endif\r\n\t#ifdef SIZEOVERLIFETIMERANDOMCURVES\r\n\t    size*=mix(getCurValueFromGradientFloat(u_SOLSizeGradient,normalizedAge),getCurValueFromGradientFloat(u_SOLSizeGradientMax,normalizedAge),a_Random0.z); \r\n\t#endif\r\n\t#ifdef SIZEOVERLIFETIMECURVESEPERATE\r\n\t\tsize*=vec2(getCurValueFromGradientFloat(u_SOLSizeGradientX,normalizedAge),getCurValueFromGradientFloat(u_SOLSizeGradientY,normalizedAge));\r\n\t#endif\r\n\t#ifdef SIZEOVERLIFETIMERANDOMCURVESSEPERATE\r\n\t    size*=vec2(mix(getCurValueFromGradientFloat(u_SOLSizeGradientX,normalizedAge),getCurValueFromGradientFloat(u_SOLSizeGradientMaxX,normalizedAge),a_Random0.z)\r\n\t    ,mix(getCurValueFromGradientFloat(u_SOLSizeGradientY,normalizedAge),getCurValueFromGradientFloat(u_SOLSizeGradientMaxY,normalizedAge),a_Random0.z));\r\n\t#endif\r\n\treturn size;\r\n}\r\n\r\n#ifdef RENDERMODE_MESH\r\nvec3 computeParticleSizeMesh(in vec3 size,in float normalizedAge)\r\n{\r\n\t#ifdef SIZEOVERLIFETIMECURVE\r\n\t\tsize*=getCurValueFromGradientFloat(u_SOLSizeGradient,normalizedAge);\r\n\t#endif\r\n\t#ifdef SIZEOVERLIFETIMERANDOMCURVES\r\n\t    size*=mix(getCurValueFromGradientFloat(u_SOLSizeGradient,normalizedAge),getCurValueFromGradientFloat(u_SOLSizeGradientMax,normalizedAge),a_Random0.z); \r\n\t#endif\r\n\t#ifdef SIZEOVERLIFETIMECURVESEPERATE\r\n\t\tsize*=vec3(getCurValueFromGradientFloat(u_SOLSizeGradientX,normalizedAge),getCurValueFromGradientFloat(u_SOLSizeGradientY,normalizedAge),getCurValueFromGradientFloat(u_SOLSizeGradientZ,normalizedAge));\r\n\t#endif\r\n\t#ifdef SIZEOVERLIFETIMERANDOMCURVESSEPERATE\r\n\t    size*=vec3(mix(getCurValueFromGradientFloat(u_SOLSizeGradientX,normalizedAge),getCurValueFromGradientFloat(u_SOLSizeGradientMaxX,normalizedAge),a_Random0.z)\r\n\t    ,mix(getCurValueFromGradientFloat(u_SOLSizeGradientY,normalizedAge),getCurValueFromGradientFloat(u_SOLSizeGradientMaxY,normalizedAge),a_Random0.z)\r\n\t\t,mix(getCurValueFromGradientFloat(u_SOLSizeGradientZ,normalizedAge),getCurValueFromGradientFloat(u_SOLSizeGradientMaxZ,normalizedAge),a_Random0.z));\r\n\t#endif\r\n\treturn size;\r\n}\r\n#endif\r\n\r\nfloat computeParticleRotationFloat(in float rotation,in float age,in float normalizedAge)\r\n{ \r\n\t#ifdef ROTATIONOVERLIFETIME\r\n\t\t#ifdef ROTATIONOVERLIFETIMECONSTANT\r\n\t\t\tfloat ageRot=u_ROLAngularVelocityConst*age;\r\n\t        rotation+=ageRot;\r\n\t\t#endif\r\n\t\t#ifdef ROTATIONOVERLIFETIMECURVE\r\n\t\t\trotation+=getTotalValueFromGradientFloat(u_ROLAngularVelocityGradient,normalizedAge);\r\n\t\t#endif\r\n\t\t#ifdef ROTATIONOVERLIFETIMERANDOMCONSTANTS\r\n\t\t\tfloat ageRot=mix(u_ROLAngularVelocityConst,u_ROLAngularVelocityConstMax,a_Random0.w)*age;\r\n\t        rotation+=ageRot;\r\n\t    #endif\r\n\t\t#ifdef ROTATIONOVERLIFETIMERANDOMCURVES\r\n\t\t\trotation+=mix(getTotalValueFromGradientFloat(u_ROLAngularVelocityGradient,normalizedAge),getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientMax,normalizedAge),a_Random0.w);\r\n\t\t#endif\r\n\t#endif\r\n\t#ifdef ROTATIONOVERLIFETIMESEPERATE\r\n\t\t#ifdef ROTATIONOVERLIFETIMECONSTANT\r\n\t\t\tfloat ageRot=u_ROLAngularVelocityConstSeprarate.z*age;\r\n\t        rotation+=ageRot;\r\n\t\t#endif\r\n\t\t#ifdef ROTATIONOVERLIFETIMECURVE\r\n\t\t\trotation+=getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientZ,normalizedAge);\r\n\t\t#endif\r\n\t\t#ifdef ROTATIONOVERLIFETIMERANDOMCONSTANTS\r\n\t\t\tfloat ageRot=mix(u_ROLAngularVelocityConstSeprarate.z,u_ROLAngularVelocityConstMaxSeprarate.z,a_Random0.w)*age;\r\n\t        rotation+=ageRot;\r\n\t    #endif\r\n\t\t#ifdef ROTATIONOVERLIFETIMERANDOMCURVES\r\n\t\t\trotation+=mix(getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientZ,normalizedAge),getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientMaxZ,normalizedAge),a_Random0.w));\r\n\t\t#endif\r\n\t#endif\r\n\treturn rotation;\r\n}\r\n\r\n#if defined(RENDERMODE_MESH)&&(defined(ROTATIONOVERLIFETIME)||defined(ROTATIONOVERLIFETIMESEPERATE))\r\nvec3 computeParticleRotationVec3(in vec3 rotation,in float age,in float normalizedAge)\r\n{ \r\n\t#ifdef ROTATIONOVERLIFETIME\r\n\t#ifdef ROTATIONOVERLIFETIMECONSTANT\r\n\t\t\tfloat ageRot=u_ROLAngularVelocityConst*age;\r\n\t        rotation+=ageRot;\r\n\t\t#endif\r\n\t\t#ifdef ROTATIONOVERLIFETIMECURVE\r\n\t\t\trotation+=getTotalValueFromGradientFloat(u_ROLAngularVelocityGradient,normalizedAge);\r\n\t\t#endif\r\n\t\t#ifdef ROTATIONOVERLIFETIMERANDOMCONSTANTS\r\n\t\t\tfloat ageRot=mix(u_ROLAngularVelocityConst,u_ROLAngularVelocityConstMax,a_Random0.w)*age;\r\n\t        rotation+=ageRot;\r\n\t    #endif\r\n\t\t#ifdef ROTATIONOVERLIFETIMERANDOMCURVES\r\n\t\t\trotation+=mix(getTotalValueFromGradientFloat(u_ROLAngularVelocityGradient,normalizedAge),getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientMax,normalizedAge),a_Random0.w);\r\n\t\t#endif\r\n\t#endif\r\n\t#ifdef ROTATIONOVERLIFETIMESEPERATE\r\n\t\t#ifdef ROTATIONOVERLIFETIMECONSTANT\r\n\t\t\tvec3 ageRot=u_ROLAngularVelocityConstSeprarate*age;\r\n\t        rotation+=ageRot;\r\n\t\t#endif\r\n\t\t#ifdef ROTATIONOVERLIFETIMECURVE\r\n\t\t\trotation+=vec3(getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientX,normalizedAge),getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientY,normalizedAge),getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientZ,normalizedAge));\r\n\t\t#endif\r\n\t\t#ifdef ROTATIONOVERLIFETIMERANDOMCONSTANTS\r\n\t\t\tvec3 ageRot=mix(u_ROLAngularVelocityConstSeprarate,u_ROLAngularVelocityConstMaxSeprarate,a_Random0.w)*age;\r\n\t        rotation+=ageRot;\r\n\t    #endif\r\n\t\t#ifdef ROTATIONOVERLIFETIMERANDOMCURVES\r\n\t\t\trotation+=vec3(mix(getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientX,normalizedAge),getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientMaxX,normalizedAge),a_Random0.w)\r\n\t        ,mix(getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientY,normalizedAge),getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientMaxY,normalizedAge),a_Random0.w)\r\n\t        ,mix(getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientZ,normalizedAge),getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientMaxZ,normalizedAge),a_Random0.w));\r\n\t\t#endif\r\n\t#endif\r\n\treturn rotation;\r\n}\r\n#endif\r\n\r\nvec2 computeParticleUV(in vec2 uv,in float normalizedAge)\r\n{ \r\n\t#ifdef TEXTURESHEETANIMATIONCURVE\r\n\t\tfloat cycleNormalizedAge=normalizedAge*u_TSACycles;\r\n\t\tfloat frame=getFrameFromGradient(u_TSAGradientUVs,cycleNormalizedAge-floor(cycleNormalizedAge));\r\n\t\tfloat totalULength=frame*u_TSASubUVLength.x;\r\n\t\tfloat floorTotalULength=floor(totalULength);\r\n\t    uv.x+=totalULength-floorTotalULength;\r\n\t\tuv.y+=floorTotalULength*u_TSASubUVLength.y;\r\n    #endif\r\n\t#ifdef TEXTURESHEETANIMATIONRANDOMCURVE\r\n\t\tfloat cycleNormalizedAge=normalizedAge*u_TSACycles;\r\n\t\tfloat uvNormalizedAge=cycleNormalizedAge-floor(cycleNormalizedAge);\r\n\t    float frame=floor(mix(getFrameFromGradient(u_TSAGradientUVs,uvNormalizedAge),getFrameFromGradient(u_TSAMaxGradientUVs,uvNormalizedAge),a_Random1.x));\r\n\t\tfloat totalULength=frame*u_TSASubUVLength.x;\r\n\t\tfloat floorTotalULength=floor(totalULength);\r\n\t    uv.x+=totalULength-floorTotalULength;\r\n\t\tuv.y+=floorTotalULength*u_TSASubUVLength.y;\r\n    #endif\r\n\treturn uv;\r\n}\r\n\r\nvoid main()\r\n{\r\n\tfloat age = u_CurrentTime - a_DirectionTime.w;\r\n\tfloat normalizedAge = age/a_ShapePositionStartLifeTime.w;\r\n\tvec3 lifeVelocity;\r\n\tif(normalizedAge<1.0)\r\n\t{ \r\n\t\tvec3 startVelocity=a_DirectionTime.xyz*a_StartSpeed;\r\n\t\t#if defined(VELOCITYOVERLIFETIMECONSTANT)||defined(VELOCITYOVERLIFETIMECURVE)||defined(VELOCITYOVERLIFETIMERANDOMCONSTANT)||defined(VELOCITYOVERLIFETIMERANDOMCURVE)\r\n\t\t\tlifeVelocity= computeParticleLifeVelocity(normalizedAge);//计算粒子生命周期速度\r\n\t\t#endif \r\n\t\tvec3 gravityVelocity=u_Gravity*age;\r\n\t\t\r\n\t\tvec4 worldRotation;\r\n\t\tif(u_SimulationSpace==0)\r\n\t\t\tworldRotation=a_SimulationWorldRotation;\r\n\t\telse\r\n\t\t\tworldRotation=u_WorldRotation;\r\n\t\t\r\n\t\tvec3 center=computeParticlePosition(startVelocity, lifeVelocity, age, normalizedAge,gravityVelocity,worldRotation);//计算粒子位置\r\n\t\r\n\t\r\n\t\t#ifdef SPHERHBILLBOARD\r\n\t\t\tvec2 corner=a_CornerTextureCoordinate.xy;//Billboard模式z轴无效\r\n\t\t\tvec3 cameraUpVector =normalize(u_CameraUp);//TODO:是否外面归一化\r\n\t\t\tvec3 sideVector = normalize(cross(u_CameraDirection,cameraUpVector));\r\n\t\t\tvec3 upVector = normalize(cross(sideVector,u_CameraDirection));\r\n\t\t\tcorner*=computeParticleSizeBillbard(a_StartSize.xy,normalizedAge);\r\n\t\t\t#if defined(ROTATIONOVERLIFETIME)||defined(ROTATIONOVERLIFETIMESEPERATE)\r\n\t\t\t\tif(u_ThreeDStartRotation){\r\n\t\t\t\t\tvec3 rotation=vec3(a_StartRotation0.xy,computeParticleRotationFloat(a_StartRotation0.z,age,normalizedAge));\r\n\t\t\t\t\tcenter += u_SizeScale.xzy*rotationByEuler(corner.x*sideVector+corner.y*upVector,rotation);\r\n\t\t\t\t}\r\n\t\t\t\telse{\r\n\t\t\t\t\tfloat rot = computeParticleRotationFloat(a_StartRotation0.x, age,normalizedAge);\r\n\t\t\t\t\tfloat c = cos(rot);\r\n\t\t\t\t\tfloat s = sin(rot);\r\n\t\t\t\t\tmat2 rotation= mat2(c, -s, s, c);\r\n\t\t\t\t\tcorner=rotation*corner;\r\n\t\t\t\t\tcenter += u_SizeScale.xzy*(corner.x*sideVector+corner.y*upVector);\r\n\t\t\t\t}\r\n\t\t\t#else\r\n\t\t\t\tif(u_ThreeDStartRotation){\r\n\t\t\t\t\tcenter += u_SizeScale.xzy*rotationByEuler(corner.x*sideVector+corner.y*upVector,a_StartRotation0);\r\n\t\t\t\t}\r\n\t\t\t\telse{\r\n\t\t\t\t\tfloat c = cos(a_StartRotation0.x);\r\n\t\t\t\t\tfloat s = sin(a_StartRotation0.x);\r\n\t\t\t\t\tmat2 rotation= mat2(c, -s, s, c);\r\n\t\t\t\t\tcorner=rotation*corner;\r\n\t\t\t\t\tcenter += u_SizeScale.xzy*(corner.x*sideVector+corner.y*upVector);\r\n\t\t\t\t}\r\n\t\t\t#endif\r\n\t\t#endif\r\n\t\r\n\t\t#ifdef STRETCHEDBILLBOARD\r\n\t\tvec2 corner=a_CornerTextureCoordinate.xy;//Billboard模式z轴无效\r\n\t\tvec3 velocity;\r\n\t\t#if defined(VELOCITYOVERLIFETIMECONSTANT)||defined(VELOCITYOVERLIFETIMECURVE)||defined(VELOCITYOVERLIFETIMERANDOMCONSTANT)||defined(VELOCITYOVERLIFETIMERANDOMCURVE)\r\n\t\t\tif(u_VOLSpaceType==0)\r\n\t\t\tvelocity=rotationByQuaternions(u_SizeScale*(startVelocity+lifeVelocity),worldRotation)+gravityVelocity;\r\n\t\t\telse\r\n\t\t\tvelocity=rotationByQuaternions(u_SizeScale*startVelocity,worldRotation)+lifeVelocity+gravityVelocity;\r\n\t\t#else\r\n\t\t\tvelocity= rotationByQuaternions(u_SizeScale*startVelocity,worldRotation)+gravityVelocity;\r\n\t\t#endif\t\r\n\t\t\tvec3 cameraUpVector = normalize(velocity);\r\n\t\t\tvec3 direction = normalize(center-u_CameraPos);\r\n\t\t\tvec3 sideVector = normalize(cross(direction,normalize(velocity)));\r\n\t\t\t\r\n\t\t\tsideVector=u_SizeScale.xzy*sideVector;\r\n\t\t\tcameraUpVector=length(vec3(u_SizeScale.x,0.0,0.0))*cameraUpVector;\r\n\t\t\t\r\n\t\t\tvec2 size=computeParticleSizeBillbard(a_StartSize.xy,normalizedAge);\r\n\t\t\t\r\n\t\t\tconst mat2 rotaionZHalfPI=mat2(0.0, -1.0, 1.0, 0.0);\r\n\t\t\tcorner=rotaionZHalfPI*corner;\r\n\t\t\tcorner.y=corner.y-abs(corner.y);\r\n\t\t\t\r\n\t\t\tfloat speed=length(velocity);//TODO:\r\n\t\t\tcenter +=sign(u_SizeScale.x)*(sign(u_StretchedBillboardLengthScale)*size.x*corner.x*sideVector+(speed*u_StretchedBillboardSpeedScale+size.y*u_StretchedBillboardLengthScale)*corner.y*cameraUpVector);\r\n\t\t#endif\r\n\t\r\n\t\t#ifdef HORIZONTALBILLBOARD\r\n\t\t\tvec2 corner=a_CornerTextureCoordinate.xy;//Billboard模式z轴无效\r\n\t\t\tconst vec3 cameraUpVector=vec3(0.0,0.0,1.0);\r\n\t\t\tconst vec3 sideVector = vec3(-1.0,0.0,0.0);\r\n\t\t\t\r\n\t\t\tfloat rot = computeParticleRotationFloat(a_StartRotation0.x, age,normalizedAge);\r\n\t\t\tfloat c = cos(rot);\r\n\t\t\tfloat s = sin(rot);\r\n\t\t\tmat2 rotation= mat2(c, -s, s, c);\r\n\t\t\tcorner=rotation*corner*cos(0.78539816339744830961566084581988);//TODO:临时缩小cos45,不确定U3D原因\r\n\t\t\tcorner*=computeParticleSizeBillbard(a_StartSize.xy,normalizedAge);\r\n\t\t\tcenter +=u_SizeScale.xzy*(corner.x*sideVector+ corner.y*cameraUpVector);\r\n\t\t#endif\r\n\t\r\n\t\t#ifdef VERTICALBILLBOARD\r\n\t\t\tvec2 corner=a_CornerTextureCoordinate.xy;//Billboard模式z轴无效\r\n\t\t\tconst vec3 cameraUpVector =vec3(0.0,1.0,0.0);\r\n\t\t\tvec3 sideVector = normalize(cross(u_CameraDirection,cameraUpVector));\r\n\t\t\t\r\n\t\t\tfloat rot = computeParticleRotationFloat(a_StartRotation0.x, age,normalizedAge);\r\n\t\t\tfloat c = cos(rot);\r\n\t\t\tfloat s = sin(rot);\r\n\t\t\tmat2 rotation= mat2(c, -s, s, c);\r\n\t\t\tcorner=rotation*corner*cos(0.78539816339744830961566084581988);//TODO:临时缩小cos45,不确定U3D原因\r\n\t\t\tcorner*=computeParticleSizeBillbard(a_StartSize.xy,normalizedAge);\r\n\t\t\tcenter +=u_SizeScale.xzy*(corner.x*sideVector+ corner.y*cameraUpVector);\r\n\t\t#endif\r\n\t\r\n\t\t#ifdef RENDERMODE_MESH\r\n\t\t\tvec3 size=computeParticleSizeMesh(a_StartSize,normalizedAge);\r\n\t\t\t#if defined(ROTATIONOVERLIFETIME)||defined(ROTATIONOVERLIFETIMESEPERATE)\r\n\t\t\t\tif(u_ThreeDStartRotation){\r\n\t\t\t\t\tvec3 rotation=vec3(a_StartRotation0.xy,computeParticleRotationFloat(a_StartRotation0.z, age,normalizedAge));\r\n\t\t\t\t\tcenter+= rotationByQuaternions(u_SizeScale*rotationByEuler(a_MeshPosition*size,rotation),worldRotation);\r\n\t\t\t\t}\r\n\t\t\t\telse{\r\n\t\t\t\t\t#ifdef ROTATIONOVERLIFETIME\r\n\t\t\t\t\t\tfloat angle=computeParticleRotationFloat(a_StartRotation0.x, age,normalizedAge);\r\n\t\t\t\t\t\tif(a_ShapePositionStartLifeTime.x!=0.0||a_ShapePositionStartLifeTime.y!=0.0){\r\n\t\t\t\t\t\t\tcenter+= (rotationByQuaternions(rotationByAxis(u_SizeScale*a_MeshPosition*size,normalize(cross(vec3(0.0,0.0,1.0),vec3(a_ShapePositionStartLifeTime.xy,0.0))),angle),worldRotation));//已验证\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse{\r\n\t\t\t\t\t\t\t#ifdef SHAPE\r\n\t\t\t\t\t\t\t\tcenter+= u_SizeScale.xzy*(rotationByQuaternions(rotationByAxis(a_MeshPosition*size,vec3(0.0,-1.0,0.0),angle),worldRotation));\r\n\t\t\t\t\t\t\t#else\r\n\t\t\t\t\t\t\t\tif(u_SimulationSpace==0)\r\n\t\t\t\t\t\t\t\t\tcenter+=rotationByAxis(u_SizeScale*a_MeshPosition*size,vec3(0.0,0.0,-1.0),angle);//已验证\r\n\t\t\t\t\t\t\t\telse if(u_SimulationSpace==1)\r\n\t\t\t\t\t\t\t\t\tcenter+=rotationByQuaternions(u_SizeScale*rotationByAxis(a_MeshPosition*size,vec3(0.0,0.0,-1.0),angle),worldRotation);//已验证\r\n\t\t\t\t\t\t\t#endif\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t#endif\r\n\t\t\t\t\t#ifdef ROTATIONOVERLIFETIMESEPERATE\r\n\t\t\t\t\t\t//TODO:是否应合并if(u_ThreeDStartRotation)分支代码,待测试\r\n\t\t\t\t\t\tvec3 angle=computeParticleRotationVec3(vec3(0.0,0.0,-a_StartRotation0.x), age,normalizedAge);\r\n\t\t\t\t\t\tcenter+= (rotationByQuaternions(rotationByEuler(u_SizeScale*a_MeshPosition*size,vec3(angle.x,angle.y,angle.z)),worldRotation));//已验证\r\n\t\t\t\t\t#endif\t\t\r\n\t\t\t\t}\r\n\t\t\t#else\r\n\t\t\t\tif(u_ThreeDStartRotation){\r\n\t\t\t\t\tcenter+= rotationByQuaternions(u_SizeScale*rotationByEuler(a_MeshPosition*size,a_StartRotation0),worldRotation);//已验证\r\n\t\t\t\t}\r\n\t\t\t\telse{\r\n\t\t\t\t\tif(a_ShapePositionStartLifeTime.x!=0.0||a_ShapePositionStartLifeTime.y!=0.0){\r\n\t\t\t\t\t\tif(u_SimulationSpace==0)\r\n\t\t\t\t\t\t\tcenter+= rotationByAxis(u_SizeScale*a_MeshPosition*size,normalize(cross(vec3(0.0,0.0,1.0),vec3(a_ShapePositionStartLifeTime.xy,0.0))),a_StartRotation0.x);\r\n\t\t\t\t\t\telse if(u_SimulationSpace==1)\r\n\t\t\t\t\t\t\tcenter+= (rotationByQuaternions(u_SizeScale*rotationByAxis(a_MeshPosition*size,normalize(cross(vec3(0.0,0.0,1.0),vec3(a_ShapePositionStartLifeTime.xy,0.0))),a_StartRotation0.x),worldRotation));//已验证\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse{\r\n\t\t\t\t\t\t#ifdef SHAPE\r\n\t\t\t\t\t\t\tif(u_SimulationSpace==0)\r\n\t\t\t\t\t\t\t\tcenter+= u_SizeScale*rotationByAxis(a_MeshPosition*size,vec3(0.0,-1.0,0.0),a_StartRotation0.x);\r\n\t\t\t\t\t\t\telse if(u_SimulationSpace==1)\r\n\t\t\t\t\t\t\t\tcenter+= rotationByQuaternions(u_SizeScale*rotationByAxis(a_MeshPosition*size,vec3(0.0,-1.0,0.0),a_StartRotation0.x),worldRotation);\t\r\n\t\t\t\t\t\t#else\r\n\t\t\t\t\t\t\tif(u_SimulationSpace==0)\r\n\t\t\t\t\t\t\t\tcenter+= rotationByAxis(u_SizeScale*a_MeshPosition*size,vec3(0.0,0.0,-1.0),a_StartRotation0.x);\r\n\t\t\t\t\t\t\telse if(u_SimulationSpace==1)\r\n\t\t\t\t\t\t\t\tcenter+= rotationByQuaternions(u_SizeScale*rotationByAxis(a_MeshPosition*size,vec3(0.0,0.0,-1.0),a_StartRotation0.x),worldRotation);//已验证\r\n\t\t\t\t\t\t#endif\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t#endif\r\n\t\t\tv_MeshColor=a_MeshColor;\r\n\t\t#endif\r\n\t\r\n\t\tgl_Position=u_Projection*u_View*vec4(center,1.0);\r\n\t\tv_Color = computeParticleColor(a_StartColor, normalizedAge);\r\n\t\t#ifdef DIFFUSEMAP\r\n\t\t\t#if defined(SPHERHBILLBOARD)||defined(STRETCHEDBILLBOARD)||defined(HORIZONTALBILLBOARD)||defined(VERTICALBILLBOARD)\r\n\t\t\t\tv_TextureCoordinate =computeParticleUV(a_CornerTextureCoordinate.zw, normalizedAge);\r\n\t\t\t#endif\r\n\t\t\t#ifdef RENDERMODE_MESH\r\n\t\t\t\tv_TextureCoordinate =computeParticleUV(a_MeshTextureCoordinate, normalizedAge);\r\n\t\t\t#endif\r\n\t\t\t\r\n\t\t\t#ifdef TILINGOFFSET\r\n\t\t\t\tv_TextureCoordinate=TransformUV(v_TextureCoordinate,u_TilingOffset);\r\n\t\t\t#endif\r\n\t\t#endif\r\n   \t}\r\n   \telse\r\n\t{\r\n\t\tgl_Position=vec4(2.0,2.0,2.0,1.0);//Discard use out of X(-1,1),Y(-1,1),Z(0,1)\r\n\t}\r\n\tgl_Position=remapGLPositionZ(gl_Position);\r\n}\r\n\r\n";

	var BRDFGLSL = "struct LayaGI\r\n{\r\n\tvec3 diffuse;\r\n\tvec3 specular;\r\n};\r\n\r\nvec4 LayaAirBRDF(in vec3 diffuseColor, in vec3 specularColor, in float oneMinusReflectivity, in float smoothness, in vec3 normal, in vec3 viewDir, in vec3 lightDir, in vec3 lightColor, in LayaGI gi)\r\n{\r\n\tfloat perceptualRoughness = SmoothnessToPerceptualRoughness(smoothness);\r\n\tvec3 halfDir = SafeNormalize(viewDir - lightDir);\r\n\t\r\n\tfloat nv = abs(dot(normal, viewDir));\r\n\t\r\n\tfloat nl = clamp(dot(normal,   -lightDir),  0.0, 1.0);\r\n\tfloat nh = clamp(dot(normal,     halfDir),  0.0, 1.0);\r\n\tfloat lv = clamp(dot(lightDir,   viewDir),  0.0, 1.0);\r\n\tfloat lh = clamp(dot(lightDir,  -halfDir),  0.0, 1.0);\r\n\t\r\n\tfloat diffuseTerm = DisneyDiffuse(nv, nl, lh, perceptualRoughness) * nl;\r\n\t\r\n\tfloat roughness = PerceptualRoughnessToRoughness(perceptualRoughness);\r\n\t\r\n\t//#if UNITY_BRDF_GGX\r\n\t // GGX with roughtness to 0 would mean no specular at all, using max(roughness, 0.002) here to match HDrenderloop roughtness remapping.\r\n\troughness = max(roughness,0.014);\r\n\tfloat V = SmithJointGGXVisibilityTerm(nl, nv, roughness);\r\n\tfloat D = GGXTerm(nh, roughness);\r\n\t\r\n\tfloat specularTerm = V * D * PI;\r\n\t\r\n\tspecularTerm = sqrt(max(0.0001, specularTerm));\r\n\tspecularTerm = max(0.0, specularTerm * nl);\r\n\t\r\n\tfloat surfaceReduction = 1.0 - 0.28 * roughness * perceptualRoughness;\r\n\tfloat grazingTerm = clamp(smoothness + (1.0 - oneMinusReflectivity), 0.0, 1.0);\r\n\t\r\n\tvec4 color;\r\n\tcolor.rgb = diffuseColor * (gi.diffuse+lightColor * diffuseTerm) \r\n\t\t\t  + specularTerm * lightColor * FresnelTerm (specularColor, lh);\r\n\t\t\t  //+ surfaceReduction * gi.specular * FresnelLerp(specularColor, vec3(grazingTerm), nv);\r\n\t\r\n\treturn color;\r\n}\r\nvec4 LayaAirStandardReflect(in vec4 albedoColor,in float metallic,in float smoothness,in LayaGI gi)\r\n{\r\n\tvec3 diffuseColor;\r\n\tvec3 specularColor;\r\n\tfloat alpha;\r\n\tfloat oneMinusReflectivity;\r\n\tdiffuseColor = DiffuseAndSpecularFromMetallic (albedoColor.rgb, metallic, specularColor, oneMinusReflectivity);\r\n\tdiffuseColor = LayaPreMultiplyAlpha(diffuseColor, albedoColor.a, oneMinusReflectivity, alpha);\r\n\tfloat perceptualRoughness = SmoothnessToPerceptualRoughness(smoothness);\r\n\tfloat roughness = PerceptualRoughnessToRoughness(perceptualRoughness);\r\n\tfloat surfaceReduction = 1.0 - 0.28 * roughness * perceptualRoughness;\r\n\tvec4 color;\r\n\tcolor.rgb = surfaceReduction * gi.specular;\r\n\tcolor.a = alpha;\r\n\treturn color;\r\n\r\n}\r\n\r\nvec4 LayaAirSpecularReflect(in vec4 albedoColor,in vec3 specularColor,in float smoothness,in LayaGI gi)\r\n{\r\n\tfloat oneMinusReflectivity;\r\n\tvec3 diffuseColor;\r\n\tfloat alpha;\r\n\t\r\n\tdiffuseColor = EnergyConservationBetweenDiffuseAndSpecular (albedoColor.rgb, specularColor, oneMinusReflectivity);\r\n\t\r\n\tdiffuseColor = LayaPreMultiplyAlpha(diffuseColor, albedoColor.a, oneMinusReflectivity, alpha);\r\n\r\n\tfloat perceptualRoughness = SmoothnessToPerceptualRoughness(smoothness);\r\n\tfloat roughness = PerceptualRoughnessToRoughness(perceptualRoughness);\r\n\tfloat surfaceReduction = 1.0 - 0.28 * roughness * perceptualRoughness;\r\n\tvec4 color;\r\n\tcolor.rgb = surfaceReduction * gi.specular;\r\n\tcolor.a = alpha;\r\n\treturn color;\r\n}";

	var PBRSpecularLightingGLSL = "#include \"PBRUtils.glsl\"\r\n#include \"BRDF.glsl\"\r\n\r\nvec4 PBRSpecularLight(in vec4 albedoColor, in vec3 specularColor, in float smoothness, in vec3 normal, in vec3 viewDir, in vec3 lightDir, in vec3 lightColor, in LayaGI gi)\r\n{\r\n\tfloat oneMinusReflectivity;\r\n\tvec3 diffuseColor;\r\n\tfloat alpha;\r\n\t\r\n\tdiffuseColor = EnergyConservationBetweenDiffuseAndSpecular (albedoColor.rgb, specularColor, oneMinusReflectivity);\r\n\t\r\n\tdiffuseColor = LayaPreMultiplyAlpha(diffuseColor, albedoColor.a, oneMinusReflectivity, alpha);\r\n\t\r\n\tvec4 color = LayaAirBRDF(diffuseColor, specularColor, oneMinusReflectivity, smoothness, normal, viewDir, lightDir, lightColor, gi);\r\n\tcolor.a = alpha;\r\n\treturn color;\r\n}\r\n\r\nvec4 PBRSpecularDiectionLight (in vec4 albedoColor, in vec3 specularColor, in float smoothness, in vec3 normal, in vec3 viewDir, in DirectionLight light, in LayaGI gi)\r\n{\r\n\tvec3 lightVec = normalize(light.direction);\r\n\treturn PBRSpecularLight(albedoColor, specularColor, smoothness, normal, viewDir, lightVec, light.color, gi);\r\n}\r\n#ifdef POINTLIGHT\r\nvec4 PBRSpecularPointLight (in vec4 albedoColor, in vec3 specularColor, in float smoothness, in vec3 normal, in vec3 viewDir, in PointLight light, in vec3 pos, in LayaGI gi)\r\n{\r\n\tvec3 lightVec = pos-light.position;\r\n\tfloat attenuate = LayaAttenuation(lightVec, 1.0/light.range);\r\n\treturn PBRSpecularLight(albedoColor, specularColor, smoothness, normal, viewDir, lightVec, light.color, gi) * attenuate;\r\n}\r\n#endif\r\nvec4 PBRSpecularSpotLight (in vec4 albedoColor, in vec3 specularColor, in float smoothness, in vec3 normal, in vec3 viewDir, in SpotLight light, in vec3 pos, in LayaGI gi)\r\n{\r\n\tvec3 lightVec =  pos - light.position;\r\n\tvec3 normalLightVec = normalize(lightVec);\r\n\tvec2 cosAngles = cos(vec2(light.spot, light.spot*0.5) * 0.5);//ConeAttenuation\r\n\tfloat dl = dot(normalize(light.direction), normalLightVec);\r\n\tdl *= smoothstep(cosAngles[0], cosAngles[1], dl);\r\n\tfloat attenuate = LayaAttenuation(lightVec, 1.0/light.range) * dl;\r\n\treturn PBRSpecularLight(albedoColor, specularColor, smoothness, normal, viewDir, lightVec, light.color, gi) * attenuate;\r\n}\r\n\r\n//vec4 PBRStandardSpotLight1 (in vec4 albedoColor, in float metallic, in float smoothness, in vec3 normal, in vec3 viewDir, in SpotLight light, in vec3 pos, in LayaGI gi)\r\n//{\r\n//\tvec4 lightCoord = u_SpotLightMatrix * vec4(pos, 1.0);\r\n//\t\r\n//\tfloat distance = dot(lightCoord, lightCoord);\r\n//\tfloat attenuate = (lightCoord.z < 0.0) ? texture2D(u_RangeTexture, vec2(distance)).w : 0.0;\r\n//\t//float attenuate = (lightCoord.z < 0.0) ? texture2D(u_AngleTexture, vec2(lightCoord.x / lightCoord.w + 0.5, lightCoord.y / lightCoord.w + 0.5)).r * texture2D(u_RangeTexture, vec2(distance)).w : 0.0;\r\n//\t//vec2 _uv = vec2(pos.x * 180.0/(2.0 * pos.z) + 0.5, pos.y * 180.0/(2.0 * pos.z) + 0.5);\r\n//\tvec3 lightVec = normalize(pos - light.cosition);\r\n//\treturn PBRStandardLight(albedoColor, metallic, smoothness, normal, viewDir, lightVec, light.color, gi) * attenuate;\r\n//}\r\n\r\nvec4 SpecularGloss(float albedoTextureAlpha, in vec2 uv0)\r\n{\r\n    vec4 sg;\r\n\t\r\n\t#ifdef SPECULARTEXTURE\r\n\t\tvec4 specularTextureColor = texture2D(u_SpecularTexture, uv0);\r\n\t\t#ifdef SMOOTHNESSSOURCE_ALBEDOTEXTURE_ALPHA\r\n\t\t\tsg.rgb = specularTextureColor.rgb;\r\n\t\t\tsg.a = albedoTextureAlpha;\r\n\t\t#else\r\n\t\t\tsg = specularTextureColor;\r\n\t\t#endif\r\n\t\tsg.a *= u_smoothnessScale;\r\n\t#else\r\n\t\tsg.rgb = u_SpecularColor.rgb;\r\n\t\t#ifdef SMOOTHNESSSOURCE_ALBEDOTEXTURE_ALPHA\r\n\t\t\tsg.a = albedoTextureAlpha * u_smoothnessScale;\r\n\t\t#else\r\n\t\t\tsg.a = u_smoothness;\r\n\t\t#endif\r\n\t#endif\r\n\t\r\n    return sg;\r\n}\r\n\r\n";

	var PBRStandardLightingGLSL = "#include \"PBRUtils.glsl\"\r\n#include \"BRDF.glsl\"\r\n\r\nvec4 PBRStandardLight(in vec4 albedoColor, in float metallic, in float smoothness, in vec3 normal, in vec3 viewDir, in vec3 lightDir, in vec3 lightColor, in LayaGI gi)\r\n{\r\n\tfloat oneMinusReflectivity;\r\n\tvec3 diffuseColor;\r\n\tvec3 specularColor;\r\n\tfloat alpha;\r\n\t\r\n\tdiffuseColor = DiffuseAndSpecularFromMetallic (albedoColor.rgb, metallic, specularColor, oneMinusReflectivity);\r\n\t\r\n\tdiffuseColor = LayaPreMultiplyAlpha(diffuseColor, albedoColor.a, oneMinusReflectivity, alpha);\r\n\t\r\n\tvec4 color = LayaAirBRDF(diffuseColor, specularColor, oneMinusReflectivity, smoothness, normal, viewDir, lightDir, lightColor, gi);\r\n\tcolor.a = alpha;\r\n\treturn color;\r\n}\r\n\r\nvec4 PBRStandardDiectionLight (in vec4 albedoColor, in float metallic, in float smoothness, in vec3 normal, in vec3 viewDir, in DirectionLight light, in LayaGI gi)\r\n{\r\n\tvec3 lightVec = normalize(light.direction);\r\n\treturn PBRStandardLight(albedoColor, metallic, smoothness, normal, viewDir, lightVec, light.color, gi);\r\n}\r\n#ifdef POINTLIGHT\r\nvec4 PBRStandardPointLight (in vec4 albedoColor, in float metallic, in float smoothness, in vec3 normal, in vec3 viewDir, in PointLight light, in vec3 pos, in LayaGI gi)\r\n{\r\n\tvec3 lightVec = pos-light.position;\r\n\tfloat attenuate = LayaAttenuation(lightVec, 1.0/light.range);\r\n\treturn PBRStandardLight(albedoColor, metallic, smoothness, normal, viewDir, lightVec, light.color, gi) * attenuate;\r\n}\r\n#endif\r\nvec4 PBRStandardSpotLight (in vec4 albedoColor, in float metallic, in float smoothness, in vec3 normal, in vec3 viewDir, in SpotLight light, in vec3 pos, in LayaGI gi)\r\n{\r\n\tvec3 lightVec =  pos - light.position;\r\n\tvec3 normalLightVec = normalize(lightVec);\r\n\tvec2 cosAngles = cos(vec2(light.spot, light.spot*0.5) * 0.5);//ConeAttenuation\r\n\tfloat dl = dot(normalize(light.direction), normalLightVec);\r\n\tdl *= smoothstep(cosAngles[0], cosAngles[1], dl);\r\n\tfloat attenuate = LayaAttenuation(lightVec, 1.0/light.range) * dl;\r\n\treturn PBRStandardLight(albedoColor, metallic, smoothness, normal, viewDir, lightVec, light.color, gi) * attenuate;\r\n\t\r\n}\r\n\r\n//vec4 PBRStandardSpotLight1 (in vec4 albedoColor, in float metallic, in float smoothness, in vec3 normal, in vec3 viewDir, in SpotLight light, in vec3 pos, in LayaGI gi)\r\n//{\r\n//\tvec4 lightCoord = u_SpotLightMatrix * vec4(pos, 1.0);\r\n//\t\r\n//\tfloat distance = dot(lightCoord, lightCoord);\r\n//\tfloat attenuate = (lightCoord.z < 0.0) ? texture2D(u_RangeTexture, vec2(distance)).w : 0.0;\r\n//\t//float attenuate = (lightCoord.z < 0.0) ? texture2D(u_AngleTexture, vec2(lightCoord.x / lightCoord.w + 0.5, lightCoord.y / lightCoord.w + 0.5)).r * texture2D(u_RangeTexture, vec2(distance)).w : 0.0;\r\n//\t//vec2 _uv = vec2(pos.x * 180.0/(2.0 * pos.z) + 0.5, pos.y * 180.0/(2.0 * pos.z) + 0.5);\r\n//\tvec3 lightVec = normalize(pos - light.position);\r\n//\treturn PBRStandardLight(albedoColor, metallic, smoothness, normal, viewDir, lightVec, light.color, gi) * attenuate;\r\n//}\r\n\r\nvec2 MetallicGloss(in float albedoTextureAlpha, in vec2 uv0)\r\n{\r\n\tvec2 mg;\r\n\t\r\n\t#ifdef METALLICGLOSSTEXTURE\r\n\t\tvec4 metallicGlossTextureColor = texture2D(u_MetallicGlossTexture, uv0);\r\n\t\t#ifdef SMOOTHNESSSOURCE_ALBEDOTEXTURE_ALPHA\r\n\t\t\tmg.r = metallicGlossTextureColor.r;\r\n\t\t\tmg.g = albedoTextureAlpha;\r\n\t\t#else\r\n\t\t    mg = metallicGlossTextureColor.ra;\r\n\t\t#endif\r\n\t\tmg.g *= u_smoothnessScale;\r\n\t#else\r\n\t\tmg.r = u_metallic;\r\n\t\t#ifdef SMOOTHNESSSOURCE_ALBEDOTEXTURE_ALPHA\r\n\t\t\tmg.g = albedoTextureAlpha * u_smoothnessScale;\r\n\t\t#else\r\n\t\t\tmg.g = u_smoothness;\r\n\t\t#endif\r\n\t#endif\r\n\t\r\n\treturn mg;\r\n}\r\n\r\n";

	var PBRUtilsGLSL = "\r\nvec3 UnpackScaleNormal(in vec2 uv0)\r\n{\r\n\t#ifdef NORMALTEXTURE\r\n\t\tvec3 normalT;\r\n\t\tvec4 normalMapSample = texture2D(u_NormalTexture, uv0);\r\n\t\tnormalT.x = 2.0 * normalMapSample.x - 1.0;\r\n\t\tnormalT.y = 1.0 - 2.0 * normalMapSample.y;\r\n\t\tnormalT.xy *= u_normalScale;\r\n\t\tnormalT.z = sqrt(1.0 - clamp(dot(normalT.xy, normalT.xy), 0.0, 1.0));\r\n\t\t\r\n\t\tvec3 T = normalize(v_Tangent);\r\n\t\tvec3 B = normalize(v_Binormal);\r\n\t\tvec3 N = normalize(v_Normal);\r\n\t\tmat3 TBN = mat3(T, B, N);\r\n\t\t\r\n\t\tvec3 bumpedNormal = TBN * normalize(normalT);\r\n\t\treturn bumpedNormal;\r\n\t#else\r\n\t\treturn normalize(v_Normal);\r\n\t#endif\r\n}\r\n\r\nvec4 DielectricSpecularColor = vec4(0.220916301, 0.220916301, 0.220916301, 1.0 - 0.220916301);\r\n\r\nfloat PI = 3.14159265359;\r\n\r\nvec3 FresnelTerm (in vec3 F0, in float cosA)\r\n{\r\n\treturn F0 + (vec3(1.0) - F0) * pow(1.0 - cosA, 5.0);\r\n}\r\n\r\nvec3 FresnelLerp (in vec3 F0, in vec3 F90, float cosA)\r\n{\r\n    float t = pow(1.0 - cosA, 5.0);\r\n    return mix(F0, F90, t);\r\n}\r\n\r\nfloat PerceptualRoughnessToRoughness(in float perceptualRoughness)\r\n{\r\n\treturn perceptualRoughness * perceptualRoughness;\r\n}\r\n\r\nfloat PerceptualRoughnessToSpecularPower(in float perceptualRoughness)\r\n{\r\n\tfloat m = PerceptualRoughnessToRoughness(perceptualRoughness);\r\n\tfloat sq = max(0.0001, m * m);\r\n\tfloat n = (2.0 / sq) - 2.0;\r\n\tn = max(n, 0.0001);\r\n\treturn n;\r\n}\r\n\r\nfloat RoughnessToPerceptualRoughness(in float roughness)\r\n{\r\n\treturn sqrt(roughness);\r\n}\r\n\r\nfloat SmoothnessToRoughness(in float smoothness)\r\n{\r\n\treturn (1.0 - smoothness) * (1.0 - smoothness);\r\n}\r\n\r\nfloat SmoothnessToPerceptualRoughness(in float smoothness)\r\n{\r\n\treturn (1.0 - smoothness);\r\n}\r\n\r\nvec3 SafeNormalize(in vec3 inVec)\r\n{\r\n\tfloat dp3 = max(0.001,dot(inVec,inVec));\r\n\treturn inVec * (1.0 / sqrt(dp3));\r\n}\r\n\r\nfloat DisneyDiffuse(in float NdotV, in float NdotL, in float LdotH, in float perceptualRoughness)\r\n{\r\n\tfloat fd90 = 0.5 + 2.0 * LdotH * LdotH * perceptualRoughness;\r\n\tfloat lightScatter\t= (1.0 + (fd90 - 1.0) * pow(1.0 - NdotL,5.0));\r\n\tfloat viewScatter\t= (1.0 + (fd90 - 1.0) * pow(1.0 - NdotV,5.0));\r\n\r\n\treturn lightScatter * viewScatter;\r\n}\r\n\r\nfloat SmithJointGGXVisibilityTerm (float NdotL, float NdotV, float roughness)\r\n{\r\n\tfloat a = roughness;\r\n\tfloat lambdaV = NdotL * (NdotV * (1.0 - a) + a);\r\n\tfloat lambdaL = NdotV * (NdotL * (1.0 - a) + a);\r\n\r\n\treturn 0.5 / (lambdaV + lambdaL + 0.00001);\r\n}\r\n\r\nfloat GGXTerm (float NdotH, float roughness)\r\n{\r\n\tfloat a2 = roughness * roughness;\r\n\tfloat d = (NdotH * a2 - NdotH) * NdotH + 1.0;\r\n\treturn 0.31830988618 * a2 / (d * d + 0.0000001);\r\n}\r\n\r\nfloat OneMinusReflectivityFromMetallic(in float metallic)\r\n{\r\n\tfloat oneMinusDielectricSpec = DielectricSpecularColor.a;\r\n\treturn oneMinusDielectricSpec - metallic * oneMinusDielectricSpec;\r\n}\r\n\r\nfloat SpecularStrength(vec3 specular)\r\n{\r\n    //(SHADER_TARGET < 30)return specular.r; \r\n    return max (max (specular.r, specular.g), specular.b);\r\n}\r\n\r\nvec3 DiffuseAndSpecularFromMetallic(in vec3 diffuseColor, in float metallic, out vec3 specularColor, out float oneMinusReflectivity)\r\n{\r\n\tspecularColor = mix(DielectricSpecularColor.rgb, diffuseColor, metallic);\r\n\toneMinusReflectivity = OneMinusReflectivityFromMetallic(metallic);\r\n\treturn diffuseColor * oneMinusReflectivity;\r\n}\r\n\r\nvec3 EnergyConservationBetweenDiffuseAndSpecular(in vec3 diffuseColor, in vec3 specularColor, out float oneMinusReflectivity)\r\n{\r\n\toneMinusReflectivity = 1.0 - SpecularStrength(specularColor);\r\n\treturn diffuseColor * oneMinusReflectivity;\r\n}\r\n\r\nvec4 Occlusion(in vec2 uv0){\r\n\t#ifdef OCCLUSIONTEXTURE\r\n\t\tvec4 occlusionTextureColor = texture2D(u_OcclusionTexture, uv0);\r\n\t\tfloat occ = occlusionTextureColor.g;\r\n\t\tfloat oneMinusT = 1.0 - u_occlusionStrength;\r\n\t\tfloat lerpOneTo = oneMinusT + occ * u_occlusionStrength;\r\n\t\treturn occlusionTextureColor * lerpOneTo;\r\n\t#else\r\n\t\treturn vec4(1.0);\r\n\t#endif\r\n}\r\n\r\nvec2 ParallaxOffset(in vec3 viewDir){\r\n\t#ifdef PARALLAXTEXTURE\r\n\t\tfloat h = texture2D(u_ParallaxTexture, v_Texcoord0).g;\r\n\t\th = h * u_parallaxScale - u_parallaxScale / 2.0;\r\n\t\tvec3 v = viewDir;\r\n\t\tv.z += 0.42;\r\n\t\tvec2 offset = h * (v.xy / v.z);\r\n\t\treturn v_Texcoord0 + offset;\r\n\t#else\r\n\t\treturn v_Texcoord0;\r\n\t#endif\r\n}\r\n\r\nvec3 ReflectCubeMap(in vec3 viewDir, in vec3 normal){\r\n\t#ifdef REFLECTMAP\r\n\t\tvec3 incident = -viewDir;\r\n\t\tvec3 reflectionVector = reflect(incident, normal);\r\n\t\tvec3 reflectionColor = textureCube(u_ReflectTexture, vec3(-reflectionVector.x, reflectionVector.yz)).rgb;\r\n\t\treturn reflectionColor * u_ReflectIntensity;\r\n\t#else\r\n\t\treturn vec3(0.0);\r\n\t#endif\r\n}\r\n\r\n\r\n\r\nvec3 LayaPreMultiplyAlpha(vec3 diffColor, float alpha, float oneMinusReflectivity, out float outModifiedAlpha)\r\n{\r\n\t#ifdef ALPHAPREMULTIPLY\r\n\t\tdiffColor *= alpha;\r\n\t\toutModifiedAlpha = 1.0 - oneMinusReflectivity + alpha * oneMinusReflectivity;\r\n\t#else\r\n\t\toutModifiedAlpha = alpha;\r\n\t#endif\r\n\treturn diffColor;\r\n}\r\n\r\n";

	var PBRSpecularPS = "#ifdef HIGHPRECISION\r\n\tprecision highp float;\r\n#else\r\n\tprecision mediump float;\r\n#endif\r\n\r\nvarying vec2 v_Texcoord0;\r\nvarying vec3 v_Normal;\r\nvarying vec3 v_Tangent;\r\nvarying vec3 v_Binormal;\r\nvarying vec3 v_ViewDir;\r\nvarying vec3 v_PositionWorld;\r\n\r\nuniform vec3 u_AmbientColor;\r\nuniform vec4 u_AlbedoColor;\r\nuniform vec4 u_SpecularColor;\r\n\r\n#ifdef ALBEDOTEXTURE\r\n\tuniform sampler2D u_AlbedoTexture;\r\n#endif\r\n#ifdef SPECULARTEXTURE\r\n\tuniform sampler2D u_SpecularTexture;\r\n#endif\r\n#ifdef NORMALTEXTURE\r\n\tuniform sampler2D u_NormalTexture;\r\n\tuniform float u_normalScale;\r\n#endif\r\n#ifdef PARALLAXTEXTURE\r\n\tuniform sampler2D u_ParallaxTexture;\r\n\tuniform float u_parallaxScale;\r\n#endif\r\n#ifdef OCCLUSIONTEXTURE\r\n\tuniform sampler2D u_OcclusionTexture;\r\n\tuniform float u_occlusionStrength;\r\n#endif\r\n#ifdef EMISSION\r\n\t#ifdef EMISSIONTEXTURE\r\n\t\tuniform sampler2D u_EmissionTexture;\r\n\t#endif\r\n\tuniform vec4 u_EmissionColor;\r\n#endif\r\n#ifdef REFLECTMAP\r\n\tuniform samplerCube u_ReflectTexture;\r\n\tuniform float u_ReflectIntensity;\r\n#endif\r\n\r\nuniform float u_AlphaTestValue;\r\nuniform float u_metallic;\r\nuniform float u_smoothness;\r\nuniform float u_smoothnessScale;\r\n\r\n\r\n\r\n#include \"Lighting.glsl\";\r\n#include \"PBRSpecularLighting.glsl\"\r\n#include \"ShadowHelper.glsl\"\r\n\r\nvarying float v_posViewZ;\r\n#ifdef RECEIVESHADOW\r\n\t#if defined(SHADOWMAP_PSSM2)||defined(SHADOWMAP_PSSM3)\r\n\t\tuniform mat4 u_lightShadowVP[4];\r\n\t#endif\r\n\t#ifdef SHADOWMAP_PSSM1 \r\n\t\tvarying vec4 v_lightMVPPos;\r\n\t#endif\r\n#endif\r\n\r\n#ifdef LEGACYSINGLELIGHTING\r\n\t#ifdef DIRECTIONLIGHT\r\n\t\tuniform DirectionLight u_DirectionLight;\r\n\t#endif\r\n\t#ifdef POINTLIGHT\r\n\t\tuniform PointLight u_PointLight;\r\n\t#endif\r\n\t#ifdef SPOTLIGHT\r\n\t\tuniform SpotLight u_SpotLight;\r\n\t#endif\r\n#else\r\n\t\tuniform mat4 u_View;\r\n\t\tuniform vec4 u_ProjectionParams;\r\n\t\tuniform vec4 u_Viewport;\r\n\t\tuniform int u_DirationLightCount;\r\n\t\tuniform sampler2D u_LightBuffer;\r\n\t\tuniform sampler2D u_LightClusterBuffer;\r\n#endif\r\n\r\n#ifdef FOG\r\n\tuniform float u_FogStart;\r\n\tuniform float u_FogRange;\r\n\tuniform vec3 u_FogColor;\r\n#endif\r\n\r\nvoid main_castShadow()\r\n{\r\n\tgl_FragColor=packDepth(v_posViewZ);\r\n\t#if defined(DIFFUSEMAP)&&defined(ALPHATEST)\r\n\t\tfloat alpha = texture2D(u_AlbedoTexture,v_Texcoord0).w;\r\n\t\tif( alpha < u_AlphaTestValue )\r\n\t\t{\r\n\t\t\tdiscard;\r\n\t\t}\r\n\t#endif\r\n}\r\n\r\nvoid main_normal()\r\n{\t\r\n\tvec3 viewDir = normalize(v_ViewDir);\r\n\t\r\n\tvec2 uv0 = ParallaxOffset(viewDir);\r\n\t\r\n\tvec4 sg;\r\n\tvec4 albedoColor;\r\n\t#ifdef ALBEDOTEXTURE\r\n\t\tvec4 albedoTextureColor = texture2D(u_AlbedoTexture, uv0);\r\n\t\talbedoColor = albedoTextureColor * u_AlbedoColor;\r\n\t\tsg = SpecularGloss(albedoTextureColor.a, uv0);\r\n\t#else\r\n\t\talbedoColor = u_AlbedoColor;\r\n\t\tsg = SpecularGloss(1.0, uv0);\r\n\t#endif\r\n\t\r\n\t#ifdef ALPHATEST\r\n\t\tif(albedoColor.a < u_AlphaTestValue)\r\n\t\t\tdiscard;\r\n\t#endif\r\n  \r\n\tvec3 normal = UnpackScaleNormal(uv0);\r\n\t\r\n\tLayaGI gi;\r\n\tgi.diffuse = u_AmbientColor * Occlusion(uv0).rgb;\r\n\tgi.specular = ReflectCubeMap(viewDir, normal);\r\n\t\r\n\t//float a = (sg.r+sg.g+sg.b) / 3.0;\r\n  \r\n\tvec4 color = vec4(0.0);\r\n\t#ifdef LEGACYSINGLELIGHTING\r\n\t\t#ifdef DIRECTIONLIGHT\r\n\t\t\tcolor += PBRSpecularDiectionLight(albedoColor, sg.rgb, sg.a, normal, viewDir, u_DirectionLight, gi);\r\n\t\t#endif\r\n\t\r\n\t\t#ifdef POINTLIGHT\r\n\t\t\tcolor.a = 0.0;\r\n\t\t\tcolor += PBRSpecularPointLight(albedoColor, sg.rgb, sg.a, normal, viewDir, u_PointLight, v_PositionWorld, gi);\r\n\t\t#endif\r\n\t\t\r\n\t\t#ifdef SPOTLIGHT\r\n\t\t\tcolor.a = 0.0;\r\n\t\t\tcolor += PBRSpecularSpotLight(albedoColor, sg.rgb, sg.a, normal, viewDir, u_SpotLight, v_PositionWorld, gi);\r\n\t\t#endif\r\n\t#else\r\n\t\t#ifdef DIRECTIONLIGHT\r\n\t\t\tfor (int i = 0; i < MAX_LIGHT_COUNT; i++) \r\n\t\t\t{\r\n\t\t\t\tif(i >= u_DirationLightCount)\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tDirectionLight directionLight = getDirectionLight(u_LightBuffer,i);\r\n\t\t\t\tcolor.a = 0.0;\r\n\t\t\t\tcolor +=PBRSpecularDiectionLight(albedoColor, sg.rgb, sg.a, normal, viewDir, directionLight, gi);\r\n\t\t\t}\r\n\t\t#endif\r\n\t\t#if defined(POINTLIGHT)||defined(SPOTLIGHT)\r\n\t\t\tivec4 clusterInfo =getClusterInfo(u_LightClusterBuffer,u_View,u_Viewport, v_PositionWorld,gl_FragCoord,u_ProjectionParams);\r\n\t\t\t#ifdef POINTLIGHT\r\n\t\t\t\tfor (int i = 0; i < MAX_LIGHT_COUNT; i++) \r\n\t\t\t\t{\r\n\t\t\t\t\tif(i >= clusterInfo.x)//PointLightCount\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tPointLight pointLight = getPointLight(u_LightBuffer,u_LightClusterBuffer,clusterInfo,i);\r\n\t\t\t\t\tcolor.a = 0.0;\r\n\t\t\t\t\tcolor +=PBRSpecularPointLight(albedoColor, sg.rgb, sg.a, normal, viewDir, pointLight, v_PositionWorld, gi);\r\n\t\t\t\t}\r\n\t\t\t#endif\r\n\t\t\t#ifdef SPOTLIGHT\r\n\t\t\t\tfor (int i = 0; i < MAX_LIGHT_COUNT; i++) \r\n\t\t\t\t{\r\n\t\t\t\t\tif(i >= clusterInfo.y)//SpotLightCount\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tSpotLight spotLight = getSpotLight(u_LightBuffer,u_LightClusterBuffer,clusterInfo,i);\r\n\t\t\t\t\tcolor.a = 0.0;\r\n\t\t\t\t\tcolor += PBRSpecularSpotLight(albedoColor, sg.rgb, sg.a, normal, viewDir, spotLight, v_PositionWorld, gi);\r\n\t\t\t\t}\r\n\t\t\t#endif\r\n\t\t#endif\r\n\t#endif\r\n\t\r\n\t#ifdef REFLECTMAP\r\n\t \tcolor += LayaAirSpecularReflect(albedoColor,sg.rgb,sg.a,gi);\r\n\t#endif\r\n\r\n\t#ifdef EMISSION\r\n\t\tvec4 emissionColor = u_EmissionColor;\r\n\t\t#ifdef EMISSIONTEXTURE\r\n\t\t\temissionColor *=  texture2D(u_EmissionTexture, uv0);\r\n\t\t#endif\r\n\t\tcolor.rgb += emissionColor.rgb;\r\n\t#endif\r\n\t\r\n\t#ifdef RECEIVESHADOW\r\n\t\tfloat shadowValue = 1.0;\r\n\t\t#ifdef SHADOWMAP_PSSM3\r\n\t\t\tshadowValue = getShadowPSSM3( u_shadowMap1,u_shadowMap2,u_shadowMap3,u_lightShadowVP,u_shadowPSSMDistance,u_shadowPCFoffset,v_PositionWorld,v_posViewZ,0.001);\r\n\t\t#endif\r\n\t\t#ifdef SHADOWMAP_PSSM2\r\n\t\t\tshadowValue = getShadowPSSM2( u_shadowMap1,u_shadowMap2,u_lightShadowVP,u_shadowPSSMDistance,u_shadowPCFoffset,v_PositionWorld,v_posViewZ,0.001);\r\n\t\t#endif \r\n\t\t#ifdef SHADOWMAP_PSSM1\r\n\t\t\tshadowValue = getShadowPSSM1( u_shadowMap1,v_lightMVPPos,u_shadowPSSMDistance,u_shadowPCFoffset,v_posViewZ,0.001);\r\n\t\t#endif\r\n\t\tgl_FragColor = vec4(color.rgb * shadowValue, color.a);\r\n\t#else\r\n\t\tgl_FragColor = color;\r\n\t#endif\r\n\t\r\n\t#ifdef FOG\r\n\t\tfloat lerpFact = clamp((1.0 / gl_FragCoord.w - u_FogStart) / u_FogRange, 0.0, 1.0);\r\n\t\tgl_FragColor.rgb = mix(gl_FragColor.rgb, u_FogColor, lerpFact);\r\n\t#endif\r\n}\r\n\r\nvoid main()\r\n{\r\n\t#ifdef CASTSHADOW\t\t\r\n\t\tmain_castShadow();\r\n\t#else\r\n\t\tmain_normal();\r\n\t#endif  \r\n}\r\n\r\n";

	var PBRSpecularVS = "#include \"Lighting.glsl\";\r\n\r\nattribute vec4 a_Position;\r\nattribute vec3 a_Normal;\r\nattribute vec4 a_Tangent0;\r\nattribute vec2 a_Texcoord0;\r\n\r\n#ifdef GPU_INSTANCE\r\n\tattribute mat4 a_MvpMatrix;\r\n#else\r\n\tuniform mat4 u_MvpMatrix;\r\n#endif\r\n\r\n#ifdef GPU_INSTANCE\r\n\tattribute mat4 a_WorldMat;\r\n#else\r\n\tuniform mat4 u_WorldMat;\r\n#endif\r\nuniform vec3 u_CameraPos;\r\n\r\nvarying vec2 v_Texcoord0;\r\nvarying vec3 v_Normal;\r\nvarying vec3 v_Tangent;\r\nvarying vec3 v_Binormal;\r\nvarying vec3 v_ViewDir;\r\nvarying vec3 v_PositionWorld;\r\n\r\n#ifdef TILINGOFFSET\r\n\tuniform vec4 u_TilingOffset;\r\n#endif\r\n\r\nvarying float v_posViewZ;\r\n#ifdef RECEIVESHADOW\r\n  #ifdef SHADOWMAP_PSSM1 \r\n\t  varying vec4 v_lightMVPPos;\r\n\t  uniform mat4 u_lightShadowVP[4];\r\n  #endif\r\n#endif\r\n\r\n#ifdef BONE\r\n\tconst int c_MaxBoneCount = 24;\r\n\tattribute vec4 a_BoneIndices;\r\n\tattribute vec4 a_BoneWeights;\r\n\tuniform mat4 u_Bones[c_MaxBoneCount];\r\n#endif\r\n\r\nvoid main_castShadow()\r\n{\r\n\tvec4 position;\r\n\t#ifdef BONE\r\n\t\tmat4 skinTransform = u_Bones[int(a_BoneIndices.x)] * a_BoneWeights.x;\r\n\t\tskinTransform += u_Bones[int(a_BoneIndices.y)] * a_BoneWeights.y;\r\n\t\tskinTransform += u_Bones[int(a_BoneIndices.z)] * a_BoneWeights.z;\r\n\t\tskinTransform += u_Bones[int(a_BoneIndices.w)] * a_BoneWeights.w;\r\n\t\tposition=skinTransform*a_Position;\r\n\t#else\r\n\t\tposition=a_Position;\r\n\t#endif\r\n\t#ifdef GPU_INSTANCE\r\n\t\tgl_Position = a_MvpMatrix * position;\r\n\t#else\r\n\t\tgl_Position = u_MvpMatrix * position;\r\n\t#endif\r\n\t \r\n\t//TODO没考虑UV动画呢\r\n\t#if defined(DIFFUSEMAP)&&defined(ALPHATEST)\r\n\t\tv_Texcoord0 = a_Texcoord0;\r\n\t#endif\r\n\tgl_Position=remapGLPositionZ(gl_Position);\r\n\tv_posViewZ = gl_Position.z;\r\n}\r\n\r\nvoid main_normal()\r\n{\r\n\tvec4 position;\r\n\t#ifdef BONE\r\n\t\tmat4 skinTransform = u_Bones[int(a_BoneIndices.x)] * a_BoneWeights.x;\r\n\t\tskinTransform += u_Bones[int(a_BoneIndices.y)] * a_BoneWeights.y;\r\n\t\tskinTransform += u_Bones[int(a_BoneIndices.z)] * a_BoneWeights.z;\r\n\t\tskinTransform += u_Bones[int(a_BoneIndices.w)] * a_BoneWeights.w;\r\n\t\tposition=skinTransform*a_Position;\r\n\t#else\r\n\t\tposition=a_Position;\r\n\t#endif\r\n\t#ifdef GPU_INSTANCE\r\n\t\tgl_Position = a_MvpMatrix * position;\r\n\t#else\r\n\t\tgl_Position = u_MvpMatrix * position;\r\n\t#endif\r\n\t\r\n\t#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)||defined(RECEIVESHADOW)||defined(REFLECTMAP)\r\n\t\tmat4 worldMat;\r\n\t\t#ifdef GPU_INSTANCE\r\n\t\t\tworldMat = a_WorldMat;\r\n\t\t#else\r\n\t\t\tworldMat = u_WorldMat;\r\n\t\t#endif\r\n\t#endif\r\n\t\r\n\t#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)||defined(REFLECTMAP)\r\n\t\tmat3 worldInvMat;\r\n\t\t#ifdef BONE\r\n\t\t\tworldInvMat=inverse(mat3(worldMat*skinTransform));\r\n\t\t#else\r\n\t\t\tworldInvMat=inverse(mat3(worldMat));\r\n\t\t#endif  \r\n\t\tv_Normal=a_Normal*worldInvMat;\r\n\t\t#if (defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT))\r\n\t\t\tv_Tangent=a_Tangent0.xyz*worldInvMat;\r\n\t\t\tv_Binormal=cross(v_Normal,v_Tangent)*a_Tangent0.w;\r\n\t\t#endif\r\n\t#endif\r\n\t\r\n\t\r\n\t#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)||defined(RECEIVESHADOW)||defined(REFLECTMAP)\r\n\t\tv_PositionWorld=(worldMat*position).xyz;\r\n\t#endif\r\n\t\r\n  \r\n\t#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)||defined(REFLECTMAP)\r\n\t\tv_ViewDir=u_CameraPos-v_PositionWorld;\r\n\t#endif\r\n\r\n\t#ifdef TILINGOFFSET\r\n\t\tv_Texcoord0=TransformUV(a_Texcoord0,u_TilingOffset);\r\n\t#else\r\n\t\tv_Texcoord0=a_Texcoord0;\r\n\t#endif\r\n  \r\n\t#ifdef RECEIVESHADOW\r\n\t\tv_posViewZ = gl_Position.w;\r\n\t\t#ifdef SHADOWMAP_PSSM1 \r\n\t\t\tv_lightMVPPos = u_lightShadowVP[0] * vec4(v_PositionWorld,1.0);\r\n\t\t#endif\r\n\t#endif\r\n\tgl_Position=remapGLPositionZ(gl_Position);\r\n}\r\n\r\nvoid main()\r\n{\r\n\t#ifdef CASTSHADOW\r\n\t\tmain_castShadow();\r\n\t#else\r\n\t\tmain_normal();\r\n\t#endif\r\n}";

	var PBRStandardPS = "#ifdef HIGHPRECISION\r\n\tprecision highp float;\r\n#else\r\n\tprecision mediump float;\r\n#endif\r\n\r\nvarying vec2 v_Texcoord0;\r\nvarying vec3 v_Normal;\r\nvarying vec3 v_Tangent;\r\nvarying vec3 v_Binormal;\r\nvarying vec3 v_ViewDir;\r\nvarying vec3 v_PositionWorld;\r\n\r\nuniform vec3 u_AmbientColor;\r\nuniform vec4 u_AlbedoColor;\r\n\r\n#ifdef ALBEDOTEXTURE\r\n\tuniform sampler2D u_AlbedoTexture;\r\n#endif\r\n#ifdef METALLICGLOSSTEXTURE\r\n\tuniform sampler2D u_MetallicGlossTexture;\r\n#endif\r\n#ifdef NORMALTEXTURE\r\n\tuniform sampler2D u_NormalTexture;\r\n\tuniform float u_normalScale;\r\n#endif\r\n#ifdef PARALLAXTEXTURE\r\n\tuniform sampler2D u_ParallaxTexture;\r\n\tuniform float u_parallaxScale;\r\n#endif\r\n#ifdef OCCLUSIONTEXTURE\r\n\tuniform sampler2D u_OcclusionTexture;\r\n\tuniform float u_occlusionStrength;\r\n#endif\r\n#ifdef EMISSION\r\n\t#ifdef EMISSIONTEXTURE\r\n\t\tuniform sampler2D u_EmissionTexture;\r\n\t#endif\r\n\tuniform vec4 u_EmissionColor;\r\n#endif\r\n#ifdef REFLECTMAP\r\n\tuniform samplerCube u_ReflectTexture;\r\n\tuniform float u_ReflectIntensity;\r\n#endif\r\n\r\nuniform float u_AlphaTestValue;\r\nuniform float u_metallic;\r\nuniform float u_smoothness;\r\nuniform float u_smoothnessScale;\r\n\r\n\r\n\r\n\r\n#include \"Lighting.glsl\";\r\n#include \"PBRStandardLighting.glsl\"\r\n#include \"ShadowHelper.glsl\"\r\n\r\nvarying float v_posViewZ;\r\n#ifdef RECEIVESHADOW\r\n\t#if defined(SHADOWMAP_PSSM2)||defined(SHADOWMAP_PSSM3)\r\n\t\tuniform mat4 u_lightShadowVP[4];\r\n\t#endif\r\n\t#ifdef SHADOWMAP_PSSM1 \r\n\t\tvarying vec4 v_lightMVPPos;\r\n\t#endif\r\n#endif\r\n\r\n#ifdef LEGACYSINGLELIGHTING\r\n\t#ifdef DIRECTIONLIGHT\r\n\t\tuniform DirectionLight u_DirectionLight;\r\n\t#endif\r\n\t#ifdef POINTLIGHT\r\n\t\tuniform PointLight u_PointLight;\r\n\t#endif\r\n\t#ifdef SPOTLIGHT\r\n\t\tuniform SpotLight u_SpotLight;\r\n\t#endif\r\n#else\r\n\t\tuniform mat4 u_View;\r\n\t\tuniform vec4 u_ProjectionParams;\r\n\t\tuniform vec4 u_Viewport;\r\n\t\tuniform int u_DirationLightCount;\r\n\t\tuniform sampler2D u_LightBuffer;\r\n\t\tuniform sampler2D u_LightClusterBuffer;\r\n#endif\r\n\r\n#ifdef FOG\r\n\tuniform float u_FogStart;\r\n\tuniform float u_FogRange;\r\n\tuniform vec3 u_FogColor;\r\n#endif\r\n\r\nvoid main_castShadow()\r\n{\r\n\tgl_FragColor=packDepth(v_posViewZ);\r\n\t#if defined(DIFFUSEMAP)&&defined(ALPHATEST)\r\n\t\tfloat alpha = texture2D(u_AlbedoTexture,v_Texcoord0).w;\r\n\t\tif( alpha < u_AlphaTestValue )\r\n\t\t{\r\n\t\t\tdiscard;\r\n\t\t}\r\n\t#endif\r\n}\r\n\r\nvoid main_normal()\r\n{\t\r\n\tvec3 viewDir = normalize(v_ViewDir);\r\n\t\r\n\tvec2 uv0 = ParallaxOffset(viewDir);\r\n\t\r\n\tvec2 mg;\r\n\tvec4 albedoColor;\r\n\t#ifdef ALBEDOTEXTURE\r\n\t\tvec4 abledoTextureColor = texture2D(u_AlbedoTexture, uv0);\r\n\t\talbedoColor = abledoTextureColor * u_AlbedoColor;\r\n\t\tmg = MetallicGloss(abledoTextureColor.a, uv0);\r\n\t#else\r\n\t\talbedoColor = u_AlbedoColor;\r\n\t\tmg = MetallicGloss(1.0, uv0);\r\n\t#endif\r\n\t\r\n\t#ifdef ALPHATEST\r\n\t\tif(albedoColor.a < u_AlphaTestValue)\r\n\t\t\tdiscard;\r\n\t#endif\r\n\t\r\n\tvec3 normal = UnpackScaleNormal(uv0);\r\n  \r\n\tLayaGI gi;\r\n\tgi.diffuse = u_AmbientColor * Occlusion(uv0).rgb;\r\n\tgi.specular = ReflectCubeMap(viewDir, normal);\r\n  \r\n\tvec4 color = vec4(0.0);\r\n\t#ifdef LEGACYSINGLELIGHTING\r\n\t\t#ifdef DIRECTIONLIGHT\r\n\t\t\tcolor += PBRStandardDiectionLight(albedoColor, mg.r, mg.g, normal, viewDir, u_DirectionLight, gi);\r\n\t\t#endif\r\n\t\r\n\t\t#ifdef POINTLIGHT\r\n\t\t\tcolor.a = 0.0;\r\n\t\t\tcolor += PBRStandardPointLight(albedoColor, mg.r, mg.g, normal, viewDir, u_PointLight, v_PositionWorld, gi);\r\n\t\t#endif\r\n\t\t\r\n\t\t#ifdef SPOTLIGHT\r\n\t\t\tcolor.a = 0.0;\r\n\t\t\tcolor += PBRStandardSpotLight(albedoColor, mg.r, mg.g, normal, viewDir, u_SpotLight, v_PositionWorld, gi);\r\n\t\t#endif\r\n\t#else\r\n\t\t#ifdef DIRECTIONLIGHT\r\n\t\t\tfor (int i = 0; i < MAX_LIGHT_COUNT; i++) \r\n\t\t\t{\r\n\t\t\t\tif(i >= u_DirationLightCount)\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tDirectionLight directionLight = getDirectionLight(u_LightBuffer,i);\r\n\t\t\t\tcolor.a = 0.0;\r\n\t\t\t\tcolor += PBRStandardDiectionLight(albedoColor, mg.r, mg.g, normal, viewDir, directionLight, gi);\r\n\t\t\t}\r\n\t\t#endif\r\n\t\t#if defined(POINTLIGHT)||defined(SPOTLIGHT)\r\n\t\t\tivec4 clusterInfo =getClusterInfo(u_LightClusterBuffer,u_View,u_Viewport, v_PositionWorld,gl_FragCoord,u_ProjectionParams);\r\n\t\t\t#ifdef POINTLIGHT\r\n\t\t\t\tfor (int i = 0; i < MAX_LIGHT_COUNT; i++) \r\n\t\t\t\t{\r\n\t\t\t\t\tif(i >= clusterInfo.x)//PointLightCount\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tPointLight pointLight = getPointLight(u_LightBuffer,u_LightClusterBuffer,clusterInfo,i);\r\n\t\t\t\t\tcolor.a = 0.0;\r\n\t\t\t\t\tcolor += PBRStandardPointLight(albedoColor, mg.r, mg.g, normal, viewDir, pointLight, v_PositionWorld, gi);\r\n\t\t\t\t}\r\n\t\t\t#endif\r\n\t\t\t#ifdef SPOTLIGHT\r\n\t\t\t\tfor (int i = 0; i < MAX_LIGHT_COUNT; i++) \r\n\t\t\t\t{\r\n\t\t\t\t\tif(i >= clusterInfo.y)//SpotLightCount\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tSpotLight spotLight = getSpotLight(u_LightBuffer,u_LightClusterBuffer,clusterInfo,i);\r\n\t\t\t\t\tcolor.a = 0.0;\r\n\t\t\t\t\tcolor += PBRStandardSpotLight(albedoColor, mg.r, mg.g, normal, viewDir, spotLight, v_PositionWorld, gi);\r\n\t\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t#endif\r\n\t\t#endif\r\n\t#endif\r\n\r\n\t\r\n\t#ifdef REFLECTMAP\r\n\t \tcolor += LayaAirStandardReflect(albedoColor,mg.r,mg.g,gi);\r\n\t#endif\r\n\r\n\t#ifdef EMISSION\r\n\t\tvec4 emissionColor = u_EmissionColor;\r\n\t\t#ifdef EMISSIONTEXTURE\r\n\t\t\temissionColor *=  texture2D(u_EmissionTexture, uv0);\r\n\t\t#endif\r\n\t\tcolor.rgb += emissionColor.rgb;\r\n\t#endif\r\n\t\r\n\t#ifdef RECEIVESHADOW\r\n\t\tfloat shadowValue = 1.0;\r\n\t\t#ifdef SHADOWMAP_PSSM3\r\n\t\t\tshadowValue = getShadowPSSM3( u_shadowMap1,u_shadowMap2,u_shadowMap3,u_lightShadowVP,u_shadowPSSMDistance,u_shadowPCFoffset,v_PositionWorld,v_posViewZ,0.001);\r\n\t\t#endif\r\n\t\t#ifdef SHADOWMAP_PSSM2\r\n\t\t\tshadowValue = getShadowPSSM2( u_shadowMap1,u_shadowMap2,u_lightShadowVP,u_shadowPSSMDistance,u_shadowPCFoffset,v_PositionWorld,v_posViewZ,0.001);\r\n\t\t#endif \r\n\t\t#ifdef SHADOWMAP_PSSM1\r\n\t\t\tshadowValue = getShadowPSSM1( u_shadowMap1,v_lightMVPPos,u_shadowPSSMDistance,u_shadowPCFoffset,v_posViewZ,0.001);\r\n\t\t#endif\r\n\t\tgl_FragColor = vec4(color.rgb * shadowValue, color.a);\r\n\t#else\r\n\t\tgl_FragColor = color;\r\n\t#endif\r\n\t\r\n\t#ifdef FOG\r\n\t\tfloat lerpFact = clamp((1.0 / gl_FragCoord.w - u_FogStart) / u_FogRange, 0.0, 1.0);\r\n\t\tgl_FragColor.rgb = mix(gl_FragColor.rgb, u_FogColor, lerpFact);\r\n\t#endif\r\n}\r\n\r\nvoid main()\r\n{\r\n\t#ifdef CASTSHADOW\t\t\r\n\t\tmain_castShadow();\r\n\t#else\r\n\t\tmain_normal();\r\n\t#endif  \r\n}";

	var PBRStandardVS = "#include \"Lighting.glsl\";\r\n\r\nattribute vec4 a_Position;\r\nattribute vec3 a_Normal;\r\nattribute vec4 a_Tangent0;\r\nattribute vec2 a_Texcoord0;\r\n\r\n#ifdef GPU_INSTANCE\r\n\tattribute mat4 a_MvpMatrix;\r\n#else\r\n\tuniform mat4 u_MvpMatrix;\r\n#endif\r\n\r\n#ifdef GPU_INSTANCE\r\n\tattribute mat4 a_WorldMat;\r\n#else\r\n\tuniform mat4 u_WorldMat;\r\n#endif\r\n\r\nuniform vec3 u_CameraPos;\r\n\r\nvarying vec2 v_Texcoord0;\r\nvarying vec3 v_Normal;\r\nvarying vec3 v_Tangent;\r\nvarying vec3 v_Binormal;\r\nvarying vec3 v_ViewDir;\r\nvarying vec3 v_PositionWorld;\r\n\r\n#ifdef TILINGOFFSET\r\n\tuniform vec4 u_TilingOffset;\r\n#endif\r\n\r\nvarying float v_posViewZ;\r\n#ifdef RECEIVESHADOW\r\n  #ifdef SHADOWMAP_PSSM1 \r\n\t  varying vec4 v_lightMVPPos;\r\n\t  uniform mat4 u_lightShadowVP[4];\r\n  #endif\r\n#endif\r\n\r\n#ifdef BONE\r\n\tconst int c_MaxBoneCount = 24;\r\n\tattribute vec4 a_BoneIndices;\r\n\tattribute vec4 a_BoneWeights;\r\n\tuniform mat4 u_Bones[c_MaxBoneCount];\r\n#endif\r\n\r\nvoid main_castShadow()\r\n{\r\n\tvec4 position;\r\n\t#ifdef BONE\r\n\t\tmat4 skinTransform = u_Bones[int(a_BoneIndices.x)] * a_BoneWeights.x;\r\n\t\tskinTransform += u_Bones[int(a_BoneIndices.y)] * a_BoneWeights.y;\r\n\t\tskinTransform += u_Bones[int(a_BoneIndices.z)] * a_BoneWeights.z;\r\n\t\tskinTransform += u_Bones[int(a_BoneIndices.w)] * a_BoneWeights.w;\r\n\t\tposition=skinTransform*a_Position;\r\n\t#else\r\n\t\tposition=a_Position;\r\n\t#endif\r\n\t#ifdef GPU_INSTANCE\r\n\t\tgl_Position = a_MvpMatrix * position;\r\n\t#else\r\n\t\tgl_Position = u_MvpMatrix * position;\r\n\t#endif\r\n\t \r\n\t//TODO没考虑UV动画呢\r\n\t#if defined(DIFFUSEMAP)&&defined(ALPHATEST)\r\n\t\tv_Texcoord0 = a_Texcoord0;\r\n\t#endif\r\n\tgl_Position=remapGLPositionZ(gl_Position);\r\n\tv_posViewZ = gl_Position.z;\r\n}\r\n\r\nvoid main_normal()\r\n{\r\n\tvec4 position;\r\n\t#ifdef BONE\r\n\t\tmat4 skinTransform = u_Bones[int(a_BoneIndices.x)] * a_BoneWeights.x;\r\n\t\tskinTransform += u_Bones[int(a_BoneIndices.y)] * a_BoneWeights.y;\r\n\t\tskinTransform += u_Bones[int(a_BoneIndices.z)] * a_BoneWeights.z;\r\n\t\tskinTransform += u_Bones[int(a_BoneIndices.w)] * a_BoneWeights.w;\r\n\t\tposition=skinTransform*a_Position;\r\n\t#else\r\n\t\tposition=a_Position;\r\n\t#endif\r\n\t#ifdef GPU_INSTANCE\r\n\t\tgl_Position = a_MvpMatrix * position;\r\n\t#else\r\n\t\tgl_Position = u_MvpMatrix * position;\r\n\t#endif\r\n\t\r\n\t#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)||defined(RECEIVESHADOW)||defined(REFLECTMAP)\r\n\t\tmat4 worldMat;\r\n\t\t#ifdef GPU_INSTANCE\r\n\t\t\tworldMat = a_WorldMat;\r\n\t\t#else\r\n\t\t\tworldMat = u_WorldMat;\r\n\t\t#endif\r\n\t#endif\r\n\t\r\n\t#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)||defined(REFLECTMAP)\r\n\t\tmat3 worldInvMat;\r\n\t\t#ifdef BONE\r\n\t\t\tworldInvMat=inverse(mat3(worldMat*skinTransform));\r\n\t\t#else\r\n\t\t\tworldInvMat=inverse(mat3(worldMat));\r\n\t\t#endif  \r\n\t\tv_Normal=a_Normal*worldInvMat;\r\n\t\t#if (defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT))\r\n\t\t\tv_Tangent=a_Tangent0.xyz*worldInvMat;\r\n\t\t\tv_Binormal=cross(v_Normal,v_Tangent)*a_Tangent0.w;\r\n\t\t#endif\r\n\t#endif\r\n\t\r\n\t\r\n\t#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)||defined(RECEIVESHADOW)||defined(REFLECTMAP)\r\n\t\tv_PositionWorld=(worldMat*position).xyz;\r\n\t#endif\r\n\t\r\n  \r\n\t#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)||defined(REFLECTMAP)||defined(REFLECTMAP)\r\n\t\tv_ViewDir=u_CameraPos-v_PositionWorld;\r\n\t#endif\r\n\r\n\t#ifdef TILINGOFFSET\r\n\t\tv_Texcoord0=TransformUV(a_Texcoord0,u_TilingOffset);\r\n\t#else\r\n\t\tv_Texcoord0=a_Texcoord0;\r\n\t#endif\r\n  \r\n\t#ifdef RECEIVESHADOW\r\n\t\tv_posViewZ = gl_Position.w;\r\n\t\t#ifdef SHADOWMAP_PSSM1 \r\n\t\t\tv_lightMVPPos = u_lightShadowVP[0] * vec4(v_PositionWorld,1.0);\r\n\t\t#endif\r\n\t#endif\r\n\tgl_Position=remapGLPositionZ(gl_Position);\r\n}\r\n\r\nvoid main()\r\n{\r\n\t#ifdef CASTSHADOW\r\n\t\tmain_castShadow();\r\n\t#else\r\n\t\tmain_normal();\r\n\t#endif\r\n}";

	var BloomVS = "#include \"Lighting.glsl\";\r\n\r\nattribute vec4 a_PositionTexcoord;\r\nvarying vec2 v_Texcoord0;\r\n\r\nvoid main() {\r\n\tgl_Position = vec4(a_PositionTexcoord.xy, 0.0, 1.0);\r\n\tv_Texcoord0 = a_PositionTexcoord.zw;\r\n\tgl_Position = remapGLPositionZ(gl_Position);\r\n}";

	var BloomDownsample13PS = "#ifdef HIGHPRECISION\r\n\tprecision highp float;\r\n#else\r\n\tprecision mediump float;\r\n#endif\r\n\r\n#include \"Colors.glsl\";\r\n#include \"Sampling.glsl\";\r\n\r\nvarying vec2 v_Texcoord0;\r\n\r\nuniform sampler2D u_MainTex;\r\nuniform vec4 u_MainTex_TexelSize;\r\n\r\nvoid fragDownsample13() {\r\n\tmediump vec4 color = downsampleBox13Tap(u_MainTex, v_Texcoord0, u_MainTex_TexelSize.xy);\r\n\tgl_FragColor = color;\r\n}\r\n\r\nvoid main() {\r\n\tfragDownsample13();\r\n}";

	var BloomDownsample4PS = "#ifdef HIGHPRECISION\r\n\tprecision highp float;\r\n#else\r\n\tprecision mediump float;\r\n#endif\r\n\r\n#include \"Colors.glsl\";\r\n#include \"Sampling.glsl\";\r\n\r\nvarying vec2 v_Texcoord0;\r\n\r\nuniform sampler2D u_MainTex;\r\nuniform vec4 u_MainTex_TexelSize;\r\n\r\nvoid fragDownsample4() {\r\n\tmediump vec4 color = downsampleBox4Tap(u_MainTex, v_Texcoord0, u_MainTex_TexelSize.xy);\r\n\tgl_FragColor = color;\r\n}\r\n\r\nvoid main() {\r\n\tfragDownsample4();\r\n}";

	var BloomPrefilter13PS = "#ifdef HIGHPRECISION\r\n\tprecision highp float;\r\n#else\r\n\tprecision mediump float;\r\n#endif\r\n\r\n#include \"Colors.glsl\";\r\n#include \"Sampling.glsl\";\r\n\r\nvarying vec2 v_Texcoord0;\r\n\r\nuniform sampler2D u_MainTex;\r\nuniform sampler2D u_AutoExposureTex;\r\nuniform vec4 u_MainTex_TexelSize;\r\nuniform vec4 u_Threshold; // x: threshold value (linear), y: threshold - knee, z: knee * 2, w: 0.25 / knee\r\nuniform vec4 u_Params; // x: clamp, yzw: unused\r\n\r\nmediump vec4 prefilter(mediump vec4 color, vec2 uv) {\r\n\tmediump float autoExposure = texture2D(u_AutoExposureTex, uv).r;\r\n\tcolor *= autoExposure;\r\n\tcolor = min(vec4(u_Params.x), color); // clamp to max\r\n\tcolor = quadraticThreshold(color, u_Threshold.x, u_Threshold.yzw);\r\n\treturn color;\r\n}\r\n\r\nvoid fragPrefilter13() {\r\n\tmediump vec4 color = downsampleBox13Tap(u_MainTex, v_Texcoord0, u_MainTex_TexelSize.xy);\r\n\tgl_FragColor = prefilter(safeHDR(color), v_Texcoord0);\r\n}\r\n\r\nvoid main() {\r\n\tfragPrefilter13();\r\n}";

	var BloomPrefilter4PS = "#ifdef HIGHPRECISION\r\n\tprecision highp float;\r\n#else\r\n\tprecision mediump float;\r\n#endif\r\n\r\n#include \"Colors.glsl\";\r\n#include \"Sampling.glsl\";\r\n\r\nvarying vec2 v_Texcoord0;\r\n\r\nuniform sampler2D u_MainTex;\r\nuniform sampler2D u_AutoExposureTex;\r\nuniform vec4 u_MainTex_TexelSize;\r\nuniform vec4 u_Threshold; // x: threshold value (linear), y: threshold - knee, z: knee * 2, w: 0.25 / knee\r\nuniform vec4 u_Params; // x: clamp, yzw: unused\r\n\r\nmediump vec4 prefilter(mediump vec4 color, vec2 uv) {\r\n\tmediump float autoExposure = texture2D(u_AutoExposureTex, uv).r;\r\n\tcolor *= autoExposure;\r\n\tcolor = min(vec4(u_Params.x), color); // clamp to max\r\n\tcolor = quadraticThreshold(color, u_Threshold.x, u_Threshold.yzw);\r\n\treturn color;\r\n}\r\n\r\nvoid fragPrefilter4() {\r\n\tmediump vec4 color = downsampleBox4Tap(u_MainTex, v_Texcoord0, u_MainTex_TexelSize.xy);\r\n\tgl_FragColor = prefilter(safeHDR(color), v_Texcoord0);\r\n}\r\n\r\nvoid main() {\r\n\tfragPrefilter4();\r\n}";

	var BloomUpsampleBoxPS = "#ifdef HIGHPRECISION\r\n\tprecision highp float;\r\n#else\r\n\tprecision mediump float;\r\n#endif\r\n\r\n#include \"Colors.glsl\";\r\n#include \"Sampling.glsl\";\r\n\r\nvarying vec2 v_Texcoord0;\r\n\r\nuniform sampler2D u_MainTex;\r\nuniform sampler2D u_BloomTex;\r\n\r\nuniform vec4 u_MainTex_TexelSize;\r\nuniform float u_SampleScale;\r\n\r\nmediump vec4 combine(mediump vec4 bloom, vec2 uv) {\r\n\tmediump vec4 color = texture2D(u_BloomTex, uv);\r\n\treturn bloom + color;\r\n}\r\n\r\nvoid fragUpsampleBox() {\r\n\tmediump vec4 bloom = upsampleBox(u_MainTex, v_Texcoord0, u_MainTex_TexelSize.xy, vec4(u_SampleScale));\r\n\tgl_FragColor = combine(bloom, v_Texcoord0);\r\n}\r\n\r\nvoid main() {\r\n\tfragUpsampleBox();\r\n}";

	var BloomUpsampleTentPS = "#ifdef HIGHPRECISION\r\n\tprecision highp float;\r\n#else\r\n\tprecision mediump float;\r\n#endif\r\n\r\n#include \"Colors.glsl\";\r\n#include \"Sampling.glsl\";\r\n\r\nvarying vec2 v_Texcoord0;\r\n\r\nuniform sampler2D u_MainTex;\r\nuniform sampler2D u_BloomTex;\r\n\r\nuniform vec4 u_MainTex_TexelSize;\r\nuniform float u_SampleScale;\r\n\r\nmediump vec4 combine(mediump vec4 bloom, vec2 uv) {\r\n\tmediump vec4 color = texture2D(u_BloomTex, uv);\r\n\treturn bloom + color;\r\n}\r\n\r\nvoid fragUpsampleTent() {\r\n\tmediump vec4 bloom = upsampleTent(u_MainTex, v_Texcoord0, u_MainTex_TexelSize.xy, vec4(u_SampleScale));\r\n\tgl_FragColor = combine(bloom, v_Texcoord0);\r\n}\r\n\r\nvoid main() {\r\n\tfragUpsampleTent();\r\n}";

	var ColorsGLSL = "#include \"StdLib.glsl\";\r\n\r\n#define EPSILON 1.0e-4\r\n\r\n// Quadratic color thresholding\r\n// curve = (threshold - knee, knee * 2, 0.25 / knee)\r\nmediump vec4 quadraticThreshold(mediump vec4 color, mediump float threshold, mediump vec3 curve) {\r\n\t// Pixel brightness\r\n\tmediump float br = max3(color.r, color.g, color.b);\r\n\r\n\t// Under-threshold part: quadratic curve\r\n\tmediump float rq = clamp(br - curve.x, 0.0, curve.y);\r\n\trq = curve.z * rq * rq;\r\n\r\n\t// Combine and apply the brightness response curve.\r\n\tcolor *= max(rq, br - threshold) / max(br, EPSILON);\r\n\r\n\treturn color;\r\n}\r\n\r\n\r\n\r\n//\r\n// sRGB transfer functions\r\n// Fast path ref: http://chilliant.blogspot.com.au/2012/08/srgb-approximations-for-hlsl.html?m=1\r\n//\r\nmediump vec3 sRGBToLinear(mediump vec3 c) {\r\n\t#ifdef USE_VERY_FAST_SRGB\r\n\t\treturn c * c;\r\n\t#elif defined(USE_FAST_SRGB)\r\n\t\treturn c * (c * (c * 0.305306011 + 0.682171111) + 0.012522878);\r\n\t#else\r\n\t\tmediump vec3 linearRGBLo = c / 12.92;\r\n\t\tmediump vec3 power=vec3(2.4, 2.4, 2.4);\r\n\t\tmediump vec3 linearRGBHi = positivePow((c + 0.055) / 1.055, power);\r\n\t\tmediump vec3 linearRGB =vec3((c.r<=0.04045) ? linearRGBLo.r : linearRGBHi.r,(c.g<=0.04045) ? linearRGBLo.g : linearRGBHi.g,(c.b<=0.04045) ? linearRGBLo.b : linearRGBHi.b);\r\n\t\treturn linearRGB;\r\n\t#endif\r\n}\r\n\r\nmediump vec4 sRGBToLinear(mediump vec4 c){\r\n    return vec4(sRGBToLinear(c.rgb), c.a);\r\n}\r\n\r\n\r\n\r\nmediump vec3 linearToSRGB(mediump vec3 c) {\r\n\t#ifdef USE_VERY_FAST_SRGB\r\n\t\treturn sqrt(c);\r\n\t#elif defined(USE_FAST_SRGB)\r\n\t\treturn max(1.055 * PositivePow(c, 0.416666667) - 0.055, 0.0);\r\n\t#else\r\n\t\tmediump vec3 sRGBLo = c * 12.92;\r\n\t\tmediump vec3 power=vec3(1.0 / 2.4, 1.0 / 2.4, 1.0 / 2.4);\r\n\t\tmediump vec3 sRGBHi = (positivePow(c, power) * 1.055) - 0.055;\r\n\t\tmediump vec3 sRGB =vec3((c.r<=0.0031308) ? sRGBLo.r : sRGBHi.r,(c.g<=0.0031308) ? sRGBLo.g : sRGBHi.g,(c.b<=0.0031308) ? sRGBLo.b : sRGBHi.b);\r\n\t\treturn sRGB;\r\n\t#endif\r\n}\r\n\r\nmediump vec4 linearToSRGB(mediump vec4 c){\r\n    return vec4(linearToSRGB(c.rgb), c.a);\r\n}";

	var CompositePS = "#ifdef HIGHPRECISION\r\n\tprecision highp float;\r\n#else\r\n\tprecision mediump float;\r\n#endif\r\n\r\n#include \"Colors.glsl\";\r\n#include \"Sampling.glsl\";\r\n\r\nvarying vec2 v_Texcoord0;\r\n\r\nuniform sampler2D u_MainTex;\r\nuniform sampler2D u_BloomTex;\r\n\r\nuniform sampler2D u_AutoExposureTex;\r\nuniform sampler2D u_Bloom_DirtTex;\r\nuniform vec4 u_BloomTex_TexelSize;\r\nuniform vec4 u_Bloom_DirtTileOffset; // xy: tiling, zw: offset\r\nuniform mediump vec3 u_Bloom_Settings;// x: sampleScale, y: intensity, z: dirt intensity\r\nuniform mediump vec3 u_Bloom_Color;\r\n\r\nvoid main() {\r\n\tmediump float autoExposure = texture2D(u_AutoExposureTex, v_Texcoord0).r;\r\n\tmediump vec4 color=vec4(0.0);\r\n\tcolor = texture2D(u_MainTex, v_Texcoord0);\r\n\t\r\n\tcolor = sRGBToLinear(color);\r\n\tcolor.rgb *= autoExposure;\r\n\t\r\n\t#if defined(BLOOM)||defined(BLOOM_LOW)\r\n\t\t#ifdef BLOOM\r\n\t\t\tmediump vec4 bloom = upsampleTent(u_BloomTex, v_Texcoord0, u_BloomTex_TexelSize.xy, vec4(u_Bloom_Settings.x));\r\n\t\t#else\r\n\t\t\tmediump vec4 bloom = upsampleBox(u_BloomTex, v_Texcoord0, u_BloomTex_TexelSize.xy, vec4(u_Bloom_Settings.x));\r\n\t\t#endif\r\n\r\n\t\t// UVs should be Distort(uv * u_Bloom_DirtTileOffset.xy + u_Bloom_DirtTileOffset.zw)\r\n\t\t// but considering we use a cover-style scale on the dirt texture the difference\r\n\t\t// isn't massive so we chose to save a few ALUs here instead in case lens distortion\r\n\t\t// is active\r\n\t\tmediump vec4 dirt =vec4(texture2D(u_Bloom_DirtTex, v_Texcoord0 * u_Bloom_DirtTileOffset.xy + u_Bloom_DirtTileOffset.zw).rgb, 0.0);\r\n\r\n\t\t// Additive bloom (artist friendly)\r\n\t\tbloom *= u_Bloom_Settings.y;\r\n\t\tdirt *= u_Bloom_Settings.z;\r\n\t\tmediump vec4 bloomColor=vec4(u_Bloom_Color, 1.0);\r\n\t\tcolor += bloom * bloomColor;\r\n\t\tcolor += dirt * bloom;\r\n\t#endif\r\n\t\r\n\tmediump vec4 finalColor = color;\r\n\tfinalColor = linearToSRGB(finalColor);\r\n\t//finalColor.rgb = Dither(finalColor.rgb, v_Texcoord0);//TODO:抖动\r\n\tgl_FragColor = finalColor;\r\n}";

	var CompositeVS = "#include \"Lighting.glsl\";\r\n\r\nattribute vec4 a_PositionTexcoord;\r\nvarying vec2 v_Texcoord0;\r\n\r\nvoid main() {\r\n\tgl_Position = vec4(a_PositionTexcoord.xy, 0.0, 1.0);\r\n\tv_Texcoord0 = a_PositionTexcoord.zw;\r\n\tgl_Position = remapGLPositionZ(gl_Position);\r\n}";

	var SamplingGLSL = "// Better, temporally stable box filtering\r\n// [Jimenez14] http://goo.gl/eomGso\r\n// . . . . . . .\r\n// . A . B . C .\r\n// . . D . E . .\r\n// . F . G . H .\r\n// . . I . J . .\r\n// . K . L . M .\r\n// . . . . . . .\r\nmediump vec4 downsampleBox13Tap(sampler2D tex, vec2 uv, vec2 texelSize)\r\n{\r\n    mediump vec4 A = texture2D(tex, uv + texelSize * vec2(-1.0, -1.0));\r\n    mediump vec4 B = texture2D(tex, uv + texelSize * vec2( 0.0, -1.0));\r\n    mediump vec4 C = texture2D(tex, uv + texelSize * vec2( 1.0, -1.0));\r\n    mediump vec4 D = texture2D(tex, uv + texelSize * vec2(-0.5, -0.5));\r\n    mediump vec4 E = texture2D(tex, uv + texelSize * vec2( 0.5, -0.5));\r\n    mediump vec4 F = texture2D(tex, uv + texelSize * vec2(-1.0,  0.0));\r\n    mediump vec4 G = texture2D(tex, uv);\r\n    mediump vec4 H = texture2D(tex, uv + texelSize * vec2( 1.0,  0.0));\r\n    mediump vec4 I = texture2D(tex, uv + texelSize * vec2(-0.5,  0.5));\r\n    mediump vec4 J = texture2D(tex, uv + texelSize * vec2( 0.5,  0.5));\r\n    mediump vec4 K = texture2D(tex, uv + texelSize * vec2(-1.0,  1.0));\r\n    mediump vec4 L = texture2D(tex, uv + texelSize * vec2( 0.0,  1.0));\r\n    mediump vec4 M = texture2D(tex, uv + texelSize * vec2( 1.0,  1.0));\r\n\r\n\tmediump vec2 scale= vec2(0.5, 0.125);\r\n    mediump vec2 div = (1.0 / 4.0) * scale;\r\n\r\n    mediump vec4 o = (D + E + I + J) * div.x;\r\n    o += (A + B + G + F) * div.y;\r\n    o += (B + C + H + G) * div.y;\r\n    o += (F + G + L + K) * div.y;\r\n    o += (G + H + M + L) * div.y;\r\n\r\n    return o;\r\n}\r\n\r\n// Standard box filtering\r\nmediump vec4 downsampleBox4Tap(sampler2D tex, vec2 uv, vec2 texelSize)\r\n{\r\n    vec4 d = texelSize.xyxy * vec4(-1.0, -1.0, 1.0, 1.0);\r\n\r\n    mediump vec4 s =  texture2D(tex, uv + d.xy);\r\n    s += texture2D(tex, uv + d.zy);\r\n    s += texture2D(tex, uv + d.xw);\r\n    s += texture2D(tex, uv + d.zw);\r\n\r\n    return s * (1.0 / 4.0);\r\n}\r\n\r\n// 9-tap bilinear upsampler (tent filter)\r\n// . . . . . . .\r\n// . 1 . 2 . 1 .\r\n// . . . . . . .\r\n// . 2 . 4 . 2 .\r\n// . . . . . . .\r\n// . 1 . 2 . 1 .\r\n// . . . . . . .\r\nmediump vec4 upsampleTent(sampler2D tex, vec2 uv, vec2 texelSize, vec4 sampleScale)\r\n{\r\n    vec4 d = texelSize.xyxy * vec4(1.0, 1.0, -1.0, 0.0) * sampleScale;\r\n\r\n    mediump vec4 s =  texture2D(tex, uv - d.xy);\r\n    s += texture2D(tex, uv - d.wy) * 2.0;\r\n    s += texture2D(tex, uv - d.zy);\r\n\r\n    s += texture2D(tex, uv + d.zw) * 2.0;\r\n    s += texture2D(tex, uv) * 4.0;\r\n    s += texture2D(tex,\tuv + d.xw) * 2.0;\r\n\r\n    s += texture2D(tex, uv + d.zy);\r\n    s += texture2D(tex, uv + d.wy) * 2.0;\r\n    s += texture2D(tex, uv + d.xy);\r\n\r\n    return s * (1.0 / 16.0);\r\n}\r\n\r\n// Standard box filtering\r\nmediump vec4 upsampleBox(sampler2D tex, vec2 uv, vec2 texelSize, vec4 sampleScale)\r\n{\r\n    vec4 d = texelSize.xyxy * vec4(-1.0, -1.0, 1.0, 1.0) * 0.5 * sampleScale;\r\n\r\n    mediump vec4 s =  texture2D(tex, uv + d.xy);\r\n    s += texture2D(tex, uv + d.zy);\r\n    s += texture2D(tex, uv + d.xw);\r\n    s += texture2D(tex, uv + d.zw);\r\n\r\n    return s * (1.0 / 4.0);\r\n}";

	var StdLibGLSL = "#define HALF_MAX       65504.0 // (2 - 2^-10) * 2^15\r\n\r\n#define FLT_EPSILON    1.192092896e-07 // Smallest positive number, such that 1.0 + FLT_EPSILON != 1.0\r\n\r\nmediump vec4 safeHDR(mediump vec4 c)\r\n{\r\n    return min(c, HALF_MAX);\r\n}\r\n\r\nfloat max3(float a, float b, float c)\r\n{\r\n    return max(max(a, b), c);\r\n}\r\n\r\nvec3 positivePow(vec3 base, vec3 power)\r\n{\r\n    return pow(max(abs(base), vec3(FLT_EPSILON, FLT_EPSILON, FLT_EPSILON)), power);\r\n}";

	var ShadowHelperGLSL = "uniform sampler2D u_shadowMap1;\r\nuniform sampler2D u_shadowMap2;\r\nuniform sampler2D u_shadowMap3;\r\nuniform vec2\t  u_shadowPCFoffset;\r\nuniform vec4     u_shadowPSSMDistance;\r\nvec4 packDepth(const in float depth)\r\n{\r\n\tconst vec4 bitShift = vec4(256.0*256.0*256.0, 256.0*256.0, 256.0, 1.0);\r\n\tconst vec4 bitMask\t= vec4(0.0, 1.0/256.0, 1.0/256.0, 1.0/256.0);\r\n\tvec4 res = mod(depth*bitShift*vec4(255), vec4(256))/vec4(255);\r\n\tres -= res.xxyz * bitMask;\r\n\treturn res;\r\n}\r\nfloat unpackDepth(const in vec4 rgbaDepth)\r\n{\r\n\tconst vec4 bitShift = vec4(1.0/(256.0*256.0*256.0), 1.0/(256.0*256.0), 1.0/256.0, 1.0);\r\n\tfloat depth = dot(rgbaDepth, bitShift);\r\n\treturn depth;\r\n}\r\nfloat tex2DPCF( sampler2D shadowMap,vec2 texcoord,vec2 invsize,float zRef )\r\n{\r\n\tvec2 texelpos =texcoord / invsize;\r\n\tvec2 lerps = fract( texelpos );\r\n\tfloat sourcevals[4];\r\n\tsourcevals[0] = float( unpackDepth(texture2D(shadowMap,texcoord)) > zRef );\r\n\tsourcevals[1] = float( unpackDepth(texture2D(shadowMap,texcoord + vec2(invsize.x,0))) > zRef );\r\n\tsourcevals[2] = float( unpackDepth(texture2D(shadowMap,texcoord + vec2(0,invsize.y))) > zRef );\r\n\tsourcevals[3] = float( unpackDepth(texture2D(shadowMap,texcoord + vec2(invsize.x, invsize.y) )) > zRef );\r\n\treturn mix( mix(sourcevals[0],sourcevals[2],lerps.y),mix(sourcevals[1],sourcevals[3],lerps.y),lerps.x );\r\n}\r\nfloat getShadowPSSM3( sampler2D shadowMap1,sampler2D shadowMap2,sampler2D shadowMap3,mat4 lightShadowVP[4],vec4 pssmDistance,vec2 shadowPCFOffset,vec3 worldPos,float posViewZ,float zBias )\r\n{\r\n\tfloat value = 1.0;\r\n\tint nPSNum = int(posViewZ>pssmDistance.x);\r\n\tnPSNum += int(posViewZ>pssmDistance.y);\r\n\tnPSNum += int(posViewZ>pssmDistance.z);\r\n\t//真SB,webgl不支持在PS中直接访问数组\r\n\tmat4 lightVP;\r\n\tif( nPSNum == 0 )\r\n\t{\r\n\t\tlightVP = lightShadowVP[1];\r\n\t}\r\n\telse if( nPSNum == 1 )\r\n\t{\r\n\t\tlightVP = lightShadowVP[2];\r\n\t}\r\n\telse if( nPSNum == 2 )\r\n\t{\r\n\t\tlightVP = lightShadowVP[3];\r\n\t}\r\n\tvec4 vLightMVPPos = lightVP * vec4(worldPos,1.0);\r\n\t//为了效率，在CPU计算/2.0 + 0.5\r\n\t//vec3 vText = (vLightMVPPos.xyz / vLightMVPPos.w)/2.0 + 0.5;\r\n\tvec3 vText = vLightMVPPos.xyz / vLightMVPPos.w;\r\n\tfloat fMyZ = vText.z - zBias;\r\n\t/*\r\n\tbvec4 bInFrustumVec = bvec4 ( vText.x >= 0.0, vText.x <= 1.0, vText.y >= 0.0, vText.y <= 1.0 );\r\n\tbool bInFrustum = all( bInFrustumVec );\r\n\tbvec2 bFrustumTestVec = bvec2( bInFrustum, fMyZ <= 1.0 );\r\n\tbool bFrustumTest = all( bFrustumTestVec );\r\n\tif ( bFrustumTest ) \r\n\t*/\r\n\tif( fMyZ <= 1.0 )\r\n\t{\r\n\t\tfloat zdepth=0.0;\r\n#ifdef SHADOWMAP_PCF3\r\n\t\tif ( nPSNum == 0 )\r\n\t\t{\r\n\t\t\tvalue =  tex2DPCF( shadowMap1, vText.xy,shadowPCFOffset,fMyZ );\r\n\t\t\tvalue += tex2DPCF( shadowMap1, vText.xy+vec2(shadowPCFOffset.xy),shadowPCFOffset,\tfMyZ );\r\n\t\t\tvalue += tex2DPCF( shadowMap1, vText.xy+vec2(shadowPCFOffset.x,0),shadowPCFOffset,\tfMyZ );\r\n\t\t\tvalue += tex2DPCF( shadowMap1, vText.xy+vec2(0,shadowPCFOffset.y),shadowPCFOffset,\tfMyZ );\r\n\t\t\tvalue = value/4.0;\r\n\t\t} \r\n\t\telse if( nPSNum == 1 )\r\n\t\t{\r\n\t\t\tvalue = tex2DPCF( shadowMap2,vText.xy,shadowPCFOffset,fMyZ);\r\n\t\t}\r\n\t\telse if( nPSNum == 2 )\r\n\t\t{\r\n\t\t\tvec4 color = texture2D( shadowMap3,vText.xy );\r\n\t\t\tzdepth = unpackDepth(color);\r\n\t\t\tvalue = float(fMyZ < zdepth);\r\n\t\t}\r\n#endif\r\n#ifdef SHADOWMAP_PCF2\r\n\t\tif ( nPSNum == 0 )\r\n\t\t{\r\n\t\t\tvalue = tex2DPCF( shadowMap1,vText.xy,shadowPCFOffset,fMyZ);\r\n\t\t}\r\n\t\telse if( nPSNum == 1 )\r\n\t\t{\r\n\t\t\tvalue = tex2DPCF( shadowMap2,vText.xy,shadowPCFOffset,fMyZ);\r\n\t\t}\r\n\t\telse if( nPSNum == 2 )\r\n\t\t{\r\n\t\t\tvec4 color = texture2D( shadowMap3,vText.xy );\r\n\t\t\tzdepth = unpackDepth(color);\r\n\t\t\tvalue = float(fMyZ < zdepth);\r\n\t\t}\r\n\r\n#endif\r\n#ifdef SHADOWMAP_PCF1\r\n\t\tif ( nPSNum == 0 )\r\n\t\t{\r\n\t\t\tvalue = tex2DPCF( shadowMap1,vText.xy,shadowPCFOffset,fMyZ);\r\n\t\t}\r\n\t\telse if( nPSNum == 1 )\r\n\t\t{\r\n\t\t\tvec4 color = texture2D( shadowMap2,vText.xy );\r\n\t\t\tzdepth = unpackDepth(color);\r\n\t\t\tvalue = float(fMyZ < zdepth);\r\n\t\t}\r\n\t\telse if( nPSNum == 2 )\r\n\t\t{\r\n\t\t\tvec4 color = texture2D( shadowMap3,vText.xy );\r\n\t\t\tzdepth = unpackDepth(color);\r\n\t\t\tvalue = float(fMyZ < zdepth);\r\n\t\t}\r\n#endif\r\n#ifdef SHADOWMAP_PCF_NO\r\n\t\tvec4 color;\r\n\t\tif ( nPSNum == 0 )\r\n\t\t{\r\n\t\t\tcolor = texture2D( shadowMap1,vText.xy );\r\n\t\t}\r\n\t\telse if( nPSNum == 1 )\r\n\t\t{\r\n\t\t\tcolor = texture2D( shadowMap2,vText.xy );\r\n\t\t}\r\n\t\telse if( nPSNum == 2 )\r\n\t\t{\r\n\t\t\tcolor = texture2D( shadowMap3,vText.xy );\r\n\t\t}\r\n\t\tzdepth = unpackDepth(color);\r\n\t\tvalue = float(fMyZ < zdepth);\r\n#endif\r\n\t}\r\n\treturn value;\r\n}\r\nfloat getShadowPSSM2( sampler2D shadowMap1,sampler2D shadowMap2,mat4 lightShadowVP[4],vec4 pssmDistance,vec2 shadowPCFOffset,vec3 worldPos,float posViewZ,float zBias )\r\n{\r\n\tfloat value = 1.0;\r\n\tint nPSNum = int(posViewZ>pssmDistance.x);\r\n\tnPSNum += int(posViewZ>pssmDistance.y);\r\n\t//真SB,webgl不支持在PS中直接访问数组\r\n\tmat4 lightVP;\r\n\tif( nPSNum == 0 )\r\n\t{\r\n\t\tlightVP = lightShadowVP[1];\r\n\t}\r\n\telse if( nPSNum == 1 )\r\n\t{\r\n\t\tlightVP = lightShadowVP[2];\r\n\t}\r\n\tvec4 vLightMVPPos = lightVP * vec4(worldPos,1.0);\r\n\t//为了效率，在CPU计算/2.0 + 0.5\r\n\t//vec3 vText = (vLightMVPPos.xyz / vLightMVPPos.w)/2.0 + 0.5;\r\n\tvec3 vText = vLightMVPPos.xyz / vLightMVPPos.w;\r\n\tfloat fMyZ = vText.z - zBias;\r\n\t/*\r\n\tbvec4 bInFrustumVec = bvec4 ( vText.x >= 0.0, vText.x <= 1.0, vText.y >= 0.0, vText.y <= 1.0 );\r\n\tbool bInFrustum = all( bInFrustumVec );\r\n\tbvec2 bFrustumTestVec = bvec2( bInFrustum, fMyZ <= 1.0 );\r\n\tbool bFrustumTest = all( bFrustumTestVec );\r\n\tif ( bFrustumTest ) \r\n\t*/\r\n\tif( fMyZ <= 1.0 )\r\n\t{\r\n\t\tfloat zdepth=0.0;\r\n#ifdef SHADOWMAP_PCF3\r\n\t\tif ( nPSNum == 0 )\r\n\t\t{\r\n\t\t\tvalue =  tex2DPCF( shadowMap1, vText.xy,shadowPCFOffset,fMyZ );\r\n\t\t\tvalue += tex2DPCF( shadowMap1, vText.xy+vec2(shadowPCFOffset.xy),shadowPCFOffset,\tfMyZ );\r\n\t\t\tvalue += tex2DPCF( shadowMap1, vText.xy+vec2(shadowPCFOffset.x,0),shadowPCFOffset,\tfMyZ );\r\n\t\t\tvalue += tex2DPCF( shadowMap1, vText.xy+vec2(0,shadowPCFOffset.y),shadowPCFOffset,\tfMyZ );\r\n\t\t\tvalue = value/4.0;\r\n\t\t}\r\n\t\telse if( nPSNum == 1 )\r\n\t\t{\r\n\t\t\tvalue = tex2DPCF( shadowMap2,vText.xy,shadowPCFOffset,fMyZ);\r\n\t\t}\r\n#endif\r\n#ifdef SHADOWMAP_PCF2\r\n\t\tif ( nPSNum == 0 )\r\n\t\t{\r\n\t\t\tvalue = tex2DPCF( shadowMap1,vText.xy,shadowPCFOffset,fMyZ);\r\n\t\t}\r\n\t\telse if( nPSNum == 1 )\r\n\t\t{\r\n\t\t\tvalue = tex2DPCF( shadowMap2,vText.xy,shadowPCFOffset,fMyZ);\r\n\t\t}\r\n#endif\r\n#ifdef SHADOWMAP_PCF1\r\n\t\tif ( nPSNum == 0 )\r\n\t\t{\r\n\t\t\tvalue = tex2DPCF( shadowMap1,vText.xy,shadowPCFOffset,fMyZ);\r\n\t\t}\r\n\t\telse if( nPSNum == 1 )\r\n\t\t{\r\n\t\t\tvec4 color = texture2D( shadowMap2,vText.xy );\r\n\t\t\tzdepth = unpackDepth(color);\r\n\t\t\tvalue = float(fMyZ < zdepth);\r\n\t\t}\r\n#endif\r\n#ifdef SHADOWMAP_PCF_NO\r\n\t\tvec4 color;\r\n\t\tif ( nPSNum == 0 )\r\n\t\t{\r\n\t\t\tcolor = texture2D( shadowMap1,vText.xy );\r\n\t\t}\r\n\t\telse if( nPSNum == 1 )\r\n\t\t{\r\n\t\t\tcolor = texture2D( shadowMap2,vText.xy );\r\n\t\t}\r\n\t\tzdepth = unpackDepth(color);\r\n\t\tvalue = float(fMyZ < zdepth);\r\n#endif\r\n\t}\r\n\treturn value;\r\n}\r\nfloat getShadowPSSM1( sampler2D shadowMap1,vec4 lightMVPPos,vec4 pssmDistance,vec2 shadowPCFOffset,float posViewZ,float zBias )\r\n{\r\n\tfloat value = 1.0;\r\n\tif( posViewZ < pssmDistance.x )\r\n\t{\r\n\t\tvec3 vText = lightMVPPos.xyz / lightMVPPos.w;\r\n\t\tfloat fMyZ = vText.z - zBias;\r\n\t\t/*\r\n\t\tbvec4 bInFrustumVec = bvec4 ( vText.x >= 0.0, vText.x <= 1.0, vText.y >= 0.0, vText.y <= 1.0 );\r\n\t\tbool bInFrustum = all( bInFrustumVec );\r\n\t\tbvec2 bFrustumTestVec = bvec2( bInFrustum, fMyZ <= 1.0 );\r\n\t\tbool bFrustumTest = all( bFrustumTestVec );\r\n\t\t*/\r\n\t\tif ( fMyZ <= 1.0 ) \r\n\t\t{\r\n\t\t\tfloat zdepth=0.0;\r\n#ifdef SHADOWMAP_PCF3\r\n\t\t\tvalue =  tex2DPCF( shadowMap1, vText.xy,shadowPCFOffset,fMyZ );\r\n\t\t\tvalue += tex2DPCF( shadowMap1, vText.xy+vec2(shadowPCFOffset.xy),shadowPCFOffset,fMyZ );\r\n\t\t\tvalue += tex2DPCF( shadowMap1, vText.xy+vec2(shadowPCFOffset.x,0),shadowPCFOffset,fMyZ );\r\n\t\t\tvalue += tex2DPCF( shadowMap1, vText.xy+vec2(0,shadowPCFOffset.y),shadowPCFOffset,fMyZ );\r\n\t\t\tvalue = value/4.0;\r\n#endif\r\n#ifdef SHADOWMAP_PCF2\t\t\r\n\t\t\tvalue = tex2DPCF( shadowMap1,vText.xy,shadowPCFOffset,fMyZ);\r\n#endif\r\n#ifdef SHADOWMAP_PCF1\r\n\t\t\tvalue = tex2DPCF( shadowMap1,vText.xy,shadowPCFOffset,fMyZ);\r\n#endif\r\n#ifdef SHADOWMAP_PCF_NO\t\t\r\n\t\t\tvec4 color = texture2D( shadowMap1,vText.xy );\r\n\t\t\tzdepth = unpackDepth(color);\r\n\t\t\tvalue = float(fMyZ < zdepth);\r\n#endif\r\n\t\t}\r\n\t}\r\n\treturn value;\r\n}";

	var SkyBoxPS = "#ifdef HIGHPRECISION\r\nprecision highp float;\r\n#else\r\nprecision mediump float;\r\n#endif\r\n\r\nvarying vec3 v_Texcoord;\r\n\r\nuniform samplerCube u_CubeTexture;\r\nuniform float u_Exposure;\r\nuniform vec4 u_TintColor;\r\n\r\n\r\nvoid main()\r\n{\t\r\n\tvec3 color=textureCube(u_CubeTexture, v_Texcoord).rgb*u_TintColor.rgb*u_Exposure*2.0;\r\n\tgl_FragColor=vec4(color,1.0);\r\n}\r\n\r\n";

	var SkyBoxVS = "#include \"Lighting.glsl\";\r\n\r\nattribute vec4 a_Position;\r\nuniform mat4 u_ViewProjection;\r\nuniform float u_Rotation;\r\nvarying vec3 v_Texcoord;\r\n\r\n\r\nvec4 rotateAroundYInDegrees (vec4 vertex, float degrees)\r\n{\r\n\tfloat angle = degrees * 3.141593 / 180.0;\r\n\tfloat sina=sin(angle);\r\n\tfloat cosa=cos(angle);\r\n\tmat2 m = mat2(cosa, -sina, sina, cosa);\r\n\treturn vec4(m*vertex.xz, vertex.yw).xzyw;\r\n}\r\n\t\t\r\nvoid main()\r\n{\r\n\tvec4 position=rotateAroundYInDegrees(a_Position,u_Rotation);\r\n\tgl_Position = u_ViewProjection*position;\r\n\tv_Texcoord=vec3(-a_Position.x,a_Position.yz);//转换坐标系\r\n\tgl_Position=remapGLPositionZ(gl_Position);\r\n}\r\n";

	var SkyBoxProceduralPS = "#ifdef HIGHPRECISION\r\n\tprecision highp float;\r\n#else\r\n\tprecision mediump float;\r\n#endif\r\n\r\n#include \"Lighting.glsl\";\r\n\r\nconst float MIE_G = -0.990;\r\nconst float MIE_G2 = 0.9801;\r\nconst float SKY_GROUND_THRESHOLD = 0.02;\r\n\r\nuniform float u_SunSize;\r\nuniform float u_SunSizeConvergence;\r\nuniform DirectionLight u_SunLight;\r\n\r\n\r\nvarying vec3 v_GroundColor;\r\nvarying vec3 v_SkyColor;\r\n\r\n\r\n#ifdef SUN_HIGH_QUALITY\r\n\tvarying vec3 v_Vertex;\r\n#elif defined(SUN_SIMPLE)\r\n\tvarying vec3 v_RayDir;\r\n#else\r\n\tvarying float v_SkyGroundFactor;\r\n#endif\r\n\r\n#if defined(SUN_HIGH_QUALITY)||defined(SUN_SIMPLE)\r\n\tvarying vec3 v_SunColor;\r\n#endif\r\n\r\n// Calculates the Mie phase function\r\nfloat getMiePhase(float eyeCos, float eyeCos2) {\r\n\tfloat temp = 1.0 + MIE_G2 - 2.0 * MIE_G * eyeCos;\r\n\ttemp = pow(temp, pow(u_SunSize,0.65) * 10.0);\r\n\ttemp = max(temp,1.0e-4); // prevent division by zero, esp. in half precision\r\n\ttemp = 1.5 * ((1.0 - MIE_G2) / (2.0 + MIE_G2)) * (1.0 + eyeCos2) / temp;\r\n\treturn temp;\r\n}\r\n\r\n// Calculates the sun shape\r\nfloat calcSunAttenuation(vec3 lightPos, vec3 ray) {\r\n\t#ifdef SUN_HIGH_QUALITY\r\n\t\tfloat focusedEyeCos = pow(clamp(dot(lightPos, ray),0.0,1.0), u_SunSizeConvergence);\r\n\t\treturn getMiePhase(-focusedEyeCos, focusedEyeCos * focusedEyeCos);\r\n\t#else //SUN_SIMPLE\r\n\t\tvec3 delta = lightPos - ray;\r\n\t\tfloat dist = length(delta);\r\n\t\tfloat spot = 1.0 - smoothstep(0.0, u_SunSize, dist);\r\n\t\treturn spot * spot;\r\n\t#endif\r\n}\r\n\r\nvoid main() {\r\n\t// if y > 1 [eyeRay.y < -SKY_GROUND_THRESHOLD] - ground\r\n\t// if y >= 0 and < 1 [eyeRay.y <= 0 and > -SKY_GROUND_THRESHOLD] - horizon\r\n\t// if y < 0 [eyeRay.y > 0] - sky\r\n\tvec3 col = vec3(0.0, 0.0, 0.0);\r\n\r\n\t#ifdef SUN_HIGH_QUALITY\r\n\t\tvec3 ray = normalize(v_Vertex);\r\n\t\tfloat y = ray.y / SKY_GROUND_THRESHOLD;\r\n\t#elif defined(SUN_SIMPLE) \r\n\t\tvec3 ray = v_RayDir;\r\n\t\tfloat y = ray.y / SKY_GROUND_THRESHOLD;\t\r\n\t#else\r\n\t\tfloat y = v_SkyGroundFactor;\r\n\t#endif\r\n\r\n\t// if we did precalculate color in vprog: just do lerp between them\r\n\tcol = mix(v_SkyColor, v_GroundColor, clamp(y,0.0,1.0));\r\n\r\n\t#if defined(SUN_HIGH_QUALITY)||defined(SUN_SIMPLE)\r\n\t\tif (y < 0.0)\r\n\t\t\tcol += v_SunColor * calcSunAttenuation(-u_SunLight.direction, -ray);\r\n\t#endif\r\n\r\n\tcol = sqrt(col);//linear space convert to gamma space\r\n\tgl_FragColor=vec4(col,1.0);\r\n}\r\n\r\n";

	var SkyBoxProceduralVS = "#ifdef HIGHPRECISION\r\n\tprecision highp float;\r\n#else\r\n\tprecision mediump float;\r\n#endif\r\n\r\n#include \"Lighting.glsl\";\r\n\r\n#define OUTER_RADIUS 1.025\r\n#define RAYLEIGH (mix(0.0, 0.0025, pow(u_AtmosphereThickness,2.5)))// Rayleigh constant Rayleigh为夜空光和极光亮度单位\r\n#define MIE 0.0010             // Mie constant 米氏散射\r\n#define SUN_BRIGHTNESS 20.0    // Sun brightness\r\n#define MAX_SCATTER 50.0 // Maximum scattering value, to prevent math overflows on Adrenos\r\n\r\nconst float SKY_GROUND_THRESHOLD = 0.02;\r\nconst float outerRadius = OUTER_RADIUS;\r\nconst float outerRadius2 = OUTER_RADIUS*OUTER_RADIUS;\r\nconst float innerRadius = 1.0;\r\nconst float innerRadius2 = 1.0;\r\nconst float cameraHeight = 0.0001;\r\n\r\nconst float HDSundiskIntensityFactor = 15.0;\r\nconst float simpleSundiskIntensityFactor = 27.0;\r\n\r\nconst float sunScale = 400.0 * SUN_BRIGHTNESS;\r\nconst float kmESun = MIE * SUN_BRIGHTNESS;\r\nconst float km4PI = MIE * 4.0 * 3.14159265;\r\nconst float scale = 1.0 / (OUTER_RADIUS - 1.0);\r\nconst float scaleDepth = 0.25;\r\nconst float scaleOverScaleDepth = (1.0 / (OUTER_RADIUS - 1.0)) / 0.25;\r\nconst float samples = 2.0; // THIS IS UNROLLED MANUALLY, DON'T TOUCH\r\n\r\n// RGB wavelengths        .35 (.62=158), .43 (.68=174), .525 (.75=190)\r\nconst vec3 c_DefaultScatteringWavelength = vec3(0.65, 0.57, 0.475);//默认散射波长\r\nconst vec3 c_VariableRangeForScatteringWavelength = vec3(0.15, 0.15, 0.15);//散射播放的可变范围\r\n\r\nattribute vec4 a_Position;\r\n\r\nuniform mat4 u_ViewProjection;\r\nuniform vec3 u_SkyTint;\r\nuniform vec3 u_GroundTint;\r\nuniform float u_Exposure;\r\nuniform float u_AtmosphereThickness;\r\nuniform DirectionLight u_SunLight;\r\n\r\nvarying vec3 v_GroundColor;\r\nvarying vec3 v_SkyColor;\r\n\r\n#ifdef SUN_HIGH_QUALITY\r\n\tvarying vec3 v_Vertex;\r\n#elif defined(SUN_SIMPLE)\r\n\tvarying vec3 v_RayDir;\r\n#else\r\n\tvarying float v_SkyGroundFactor;\r\n#endif\r\n\r\n#if defined(SUN_HIGH_QUALITY)||defined(SUN_SIMPLE)\r\n\tvarying vec3 v_SunColor;\r\n#endif\r\n\r\n// Calculates the Rayleigh phase function\r\nfloat getRayleighPhase(vec3 light, vec3 ray) \r\n{\r\n\tfloat eyeCos = dot(light, ray);\r\n\treturn 0.75 + 0.75*eyeCos*eyeCos;\r\n}\r\n\r\nfloat scaleAngle(float inCos)\r\n{\r\n\tfloat x = 1.0 - inCos;\r\n\treturn 0.25 * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25))));\r\n}\r\n\r\n\r\nvoid main () {\r\n\tgl_Position = u_ViewProjection*a_Position;\r\n\r\n\tvec3 skyTintInGammaSpace = u_SkyTint;//支持非GAMMA空间后要调整\r\n\tvec3 scatteringWavelength = mix(c_DefaultScatteringWavelength-c_VariableRangeForScatteringWavelength,c_DefaultScatteringWavelength+c_VariableRangeForScatteringWavelength,vec3(1.0) - skyTintInGammaSpace); // using Tint in sRGB+ gamma allows for more visually linear interpolation and to keep (0.5) at (128, gray in sRGB) point\r\n\tvec3 invWavelength = 1.0 / pow(scatteringWavelength, vec3(4.0));\r\n\r\n\tfloat krESun = RAYLEIGH * SUN_BRIGHTNESS;\r\n\tfloat kr4PI = RAYLEIGH * 4.0 * 3.14159265;\r\n\r\n\tvec3 cameraPos = vec3(0.0,innerRadius + cameraHeight,0.0); // The camera's current position\r\n\r\n\t// Get the ray from the camera to the vertex and its length (which is the far point of the ray passing through the atmosphere)\r\n\tvec3 eyeRay = normalize(a_Position.xyz);\r\n\r\n\tfloat far = 0.0;\r\n\tvec3 cIn, cOut;\r\n\tif (eyeRay.y >= 0.0) {// Sky\r\n\t\t// Calculate the length of the \"atmosphere\"\r\n\t\tfar = sqrt(outerRadius2 + innerRadius2 * eyeRay.y * eyeRay.y - innerRadius2) - innerRadius * eyeRay.y;\r\n\r\n\t\t// Calculate the ray's starting position, then calculate its scattering offset\r\n\t\tfloat height = innerRadius + cameraHeight;\r\n\t\tfloat depth = exp(scaleOverScaleDepth * -cameraHeight);\r\n\t\tfloat startAngle = dot(eyeRay, cameraPos) / height;\r\n\t\tfloat startOffset = depth*scaleAngle(startAngle);\r\n\r\n\t\t// Initialize the scattering loop variables\r\n\t\tfloat sampleLength = far / samples;\r\n\t\tfloat scaledLength = sampleLength * scale;\r\n\t\tvec3 sampleRay = eyeRay * sampleLength;\r\n\t\tvec3 samplePoint = cameraPos + sampleRay * 0.5;\r\n\r\n\t\tvec3 frontColor = vec3(0.0);\r\n\t\t//unrolling this manually to avoid some platform for loop slow\r\n\t\t{\r\n\t\t\tfloat height = length(samplePoint);\r\n\t\t\tfloat depth = exp(scaleOverScaleDepth * (innerRadius - height));\r\n\t\t\tfloat lightAngle = dot(-u_SunLight.direction, samplePoint) / height;\r\n\t\t\tfloat cameraAngle = dot(eyeRay, samplePoint) / height;\r\n\t\t\tfloat scatter = (startOffset + depth*(scaleAngle(lightAngle) - scaleAngle(cameraAngle)));\r\n\t\t\tvec3 attenuate = exp(-clamp(scatter, 0.0, MAX_SCATTER) * (invWavelength * kr4PI + km4PI));\r\n\r\n\t\t\tfrontColor += attenuate * (depth * scaledLength);\r\n\t\t\tsamplePoint += sampleRay;\r\n\t\t}\r\n\t\t{\r\n\t\t\tfloat height = length(samplePoint);\r\n\t\t\tfloat depth = exp(scaleOverScaleDepth * (innerRadius - height));\r\n\t\t\tfloat lightAngle = dot(-u_SunLight.direction, samplePoint) / height;\r\n\t\t\tfloat cameraAngle = dot(eyeRay, samplePoint) / height;\r\n\t\t\tfloat scatter = (startOffset + depth*(scaleAngle(lightAngle) - scaleAngle(cameraAngle)));\r\n\t\t\tvec3 attenuate = exp(-clamp(scatter, 0.0, MAX_SCATTER) * (invWavelength * kr4PI + km4PI));\r\n\r\n\t\t\tfrontColor += attenuate * (depth * scaledLength);\r\n\t\t\tsamplePoint += sampleRay;\r\n\t\t}\r\n\r\n\t\t// Finally, scale the Mie and Rayleigh colors and set up the varying variables for the pixel shader\r\n\t\tcIn = frontColor * (invWavelength * krESun);\r\n\t\tcOut = frontColor * kmESun;\r\n\t} else {// Ground\r\n\t\tfar = (-cameraHeight) / (min(-0.001, eyeRay.y));\r\n\t\tvec3 pos = cameraPos + far * eyeRay;\r\n\r\n\t\t// Calculate the ray's starting position, then calculate its scattering offset\r\n\t\tfloat depth = exp((-cameraHeight) * (1.0/scaleDepth));\r\n\t\tfloat cameraAngle = dot(-eyeRay, pos);\r\n\t\tfloat lightAngle = dot(-u_SunLight.direction, pos);\r\n\t\tfloat cameraScale = scaleAngle(cameraAngle);\r\n\t\tfloat lightScale = scaleAngle(lightAngle);\r\n\t\tfloat cameraOffset = depth*cameraScale;\r\n\t\tfloat temp = lightScale + cameraScale;\r\n\r\n\t\t// Initialize the scattering loop variables\r\n\t\tfloat sampleLength = far / samples;\r\n\t\tfloat scaledLength = sampleLength * scale;\r\n\t\tvec3 sampleRay = eyeRay * sampleLength;\r\n\t\tvec3 samplePoint = cameraPos + sampleRay * 0.5;\r\n\r\n\t\t// Now loop through the sample rays\r\n\t\tvec3 frontColor = vec3(0.0, 0.0, 0.0);\r\n\t\tvec3 attenuate;\r\n\r\n\t\t// Loop removed because we kept hitting SM2.0 temp variable limits. Doesn't affect the image too much.\r\n\t\t{\r\n\t\t\tfloat height = length(samplePoint);\r\n\t\t\tfloat depth = exp(scaleOverScaleDepth * (innerRadius - height));\r\n\t\t\tfloat scatter = depth*temp - cameraOffset;\r\n\t\t\tattenuate = exp(-clamp(scatter, 0.0, MAX_SCATTER) * (invWavelength * kr4PI + km4PI));\r\n\t\t\tfrontColor += attenuate * (depth * scaledLength);\r\n\t\t\tsamplePoint += sampleRay;\r\n\t\t}\r\n\r\n\t\tcIn = frontColor * (invWavelength * krESun + kmESun);\r\n\t\tcOut = clamp(attenuate, 0.0, 1.0);\r\n\t}\r\n\r\n\t#ifdef SUN_HIGH_QUALITY\r\n\t\tv_Vertex = -a_Position.xyz;\r\n\t#elif defined(SUN_SIMPLE) \r\n\t\tv_RayDir = -eyeRay;\r\n\t#else\r\n\t\tv_SkyGroundFactor = -eyeRay.y / SKY_GROUND_THRESHOLD;\r\n\t#endif\r\n\r\n\t// if we want to calculate color in vprog:\r\n\t// in case of linear: multiply by _Exposure in here (even in case of lerp it will be common multiplier, so we can skip mul in fshader)\r\n\tv_GroundColor = u_Exposure * (cIn + u_GroundTint*u_GroundTint * cOut);//u_GroundColor*u_GroundColor is gamma space convert to linear space\r\n\tv_SkyColor    = u_Exposure * (cIn * getRayleighPhase(-u_SunLight.direction, -eyeRay));\r\n\r\n\t\r\n\t// The sun should have a stable intensity in its course in the sky. Moreover it should match the highlight of a purely specular material.\r\n\t// This matching was done using the Unity3D standard shader BRDF1 on the 5/31/2017\r\n\t// Finally we want the sun to be always bright even in LDR thus the normalization of the lightColor for low intensity.\r\n\tfloat lightColorIntensity = clamp(length(u_SunLight.color), 0.25, 1.0);\r\n\r\n\t#ifdef SUN_HIGH_QUALITY \r\n\t\tv_SunColor = HDSundiskIntensityFactor * clamp(cOut,0.0,1.0) * u_SunLight.color / lightColorIntensity;\r\n\t#elif defined(SUN_SIMPLE) \r\n\t\tv_SunColor = simpleSundiskIntensityFactor * clamp(cOut * sunScale,0.0,1.0) * u_SunLight.color / lightColorIntensity;\r\n\t#endif\r\n\tgl_Position=remapGLPositionZ(gl_Position);\r\n}\r\n";

	var TrailPS = "#ifdef HIGHPRECISION\r\n\tprecision highp float;\r\n#else\r\n\tprecision mediump float;\r\n#endif\r\n\r\nuniform sampler2D u_MainTexture;\r\nuniform vec4 u_MainColor;\r\n\r\nvarying vec2 v_Texcoord0;\r\nvarying vec4 v_Color;\r\n\r\nvoid main()\r\n{\r\n\tvec4 color = 2.0 * u_MainColor * v_Color;\r\n\t#ifdef MAINTEXTURE\r\n\t\tvec4 mainTextureColor = texture2D(u_MainTexture, v_Texcoord0);\r\n\t\tcolor *= mainTextureColor;\r\n\t#endif\r\n\tgl_FragColor = color;\r\n}\r\n\r\n     ";

	var TrailVS = "#include \"Lighting.glsl\";\r\n\r\nattribute vec3 a_Position;\r\nattribute vec3 a_OffsetVector;\r\nattribute vec4 a_Color;\r\nattribute float a_Texcoord0X;\r\nattribute float a_Texcoord0Y;\r\nattribute float a_BirthTime;\r\n\r\nuniform mat4 u_View;\r\nuniform mat4 u_Projection;\r\n\r\nuniform vec4 u_TilingOffset;\r\n\r\nuniform float u_CurTime;\r\nuniform float u_LifeTime;\r\nuniform vec4 u_WidthCurve[10];\r\nuniform int u_WidthCurveKeyLength;\r\n\r\nvarying vec2 v_Texcoord0;\r\nvarying vec4 v_Color;\r\n\r\nfloat hermiteInterpolate(float t, float outTangent, float inTangent, float duration, float value1, float value2)\r\n{\r\n\tfloat t2 = t * t;\r\n\tfloat t3 = t2 * t;\r\n\tfloat a = 2.0 * t3 - 3.0 * t2 + 1.0;\r\n\tfloat b = t3 - 2.0 * t2 + t;\r\n\tfloat c = t3 - t2;\r\n\tfloat d = -2.0 * t3 + 3.0 * t2;\r\n\treturn a * value1 + b * outTangent * duration + c * inTangent * duration + d * value2;\r\n}\r\n\r\nfloat getCurWidth(in float normalizeTime)\r\n{\r\n\tfloat width;\r\n\tif(normalizeTime == 0.0){\r\n\t\twidth=u_WidthCurve[0].w;\r\n\t}\r\n\telse if(normalizeTime >= 1.0){\r\n\t\twidth=u_WidthCurve[u_WidthCurveKeyLength - 1].w;\r\n\t}\r\n\telse{\r\n\t\tfor(int i = 0; i < 10; i ++ )\r\n\t\t{\r\n\t\t\tif(normalizeTime == u_WidthCurve[i].x){\r\n\t\t\t\twidth=u_WidthCurve[i].w;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tvec4 lastFrame = u_WidthCurve[i];\r\n\t\t\tvec4 nextFrame = u_WidthCurve[i + 1];\r\n\t\t\tif(normalizeTime > lastFrame.x && normalizeTime < nextFrame.x)\r\n\t\t\t{\r\n\t\t\t\tfloat duration = nextFrame.x - lastFrame.x;\r\n\t\t\t\tfloat t = (normalizeTime - lastFrame.x) / duration;\r\n\t\t\t\tfloat outTangent = lastFrame.z;\r\n\t\t\t\tfloat inTangent = nextFrame.y;\r\n\t\t\t\tfloat value1 = lastFrame.w;\r\n\t\t\t\tfloat value2 = nextFrame.w;\r\n\t\t\t\twidth=hermiteInterpolate(t, outTangent, inTangent, duration, value1, value2);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn width;\r\n}\t\r\n\r\nvoid main()\r\n{\r\n\tfloat normalizeTime = (u_CurTime - a_BirthTime) / u_LifeTime;\r\n\t\r\n\t#ifdef TILINGOFFSET\r\n\t\tv_Texcoord0 = vec2(a_Texcoord0X, 1.0 - a_Texcoord0Y) * u_TilingOffset.xy + u_TilingOffset.zw;\r\n\t#else\r\n\t\tv_Texcoord0 = vec2(a_Texcoord0X, a_Texcoord0Y);\r\n\t#endif\r\n\t\r\n\tv_Color = a_Color;\r\n\t\r\n\tgl_Position = u_Projection * u_View * vec4(a_Position + a_OffsetVector * getCurWidth(normalizeTime),1.0);\r\n\tgl_Position=remapGLPositionZ(gl_Position);\r\n}\r\n";

	var UnlitPS = "#ifdef HIGHPRECISION\r\n\tprecision highp float;\r\n#else\r\n\tprecision mediump float;\r\n#endif\r\n\r\n#if defined(COLOR)&&defined(ENABLEVERTEXCOLOR)\r\n\tvarying vec4 v_Color;\r\n#endif\r\n\r\n#ifdef ALBEDOTEXTURE\r\n\tuniform sampler2D u_AlbedoTexture;\r\n\tvarying vec2 v_Texcoord0;\r\n#endif\r\n\r\nuniform vec4 u_AlbedoColor;\r\n\r\n#ifdef ALPHATEST\r\n\tuniform float u_AlphaTestValue;\r\n#endif\r\n\r\n#ifdef FOG\r\n\tuniform float u_FogStart;\r\n\tuniform float u_FogRange;\r\n\t#ifdef ADDTIVEFOG\r\n\t#else\r\n\t\tuniform vec3 u_FogColor;\r\n\t#endif\r\n#endif\r\n\r\nvoid main()\r\n{\r\n\tvec4 color =  u_AlbedoColor;\r\n\t#ifdef ALBEDOTEXTURE\r\n\t\tcolor *= texture2D(u_AlbedoTexture, v_Texcoord0);\r\n\t#endif\r\n\t#if defined(COLOR)&&defined(ENABLEVERTEXCOLOR)\r\n\t\tcolor *= v_Color;\r\n\t#endif\r\n\t\r\n\t#ifdef ALPHATEST\r\n\t\tif(color.a < u_AlphaTestValue)\r\n\t\t\tdiscard;\r\n\t#endif\r\n\t\r\n\tgl_FragColor = color;\r\n\t\r\n\t#ifdef FOG\r\n\t\tfloat lerpFact = clamp((1.0 / gl_FragCoord.w - u_FogStart) / u_FogRange, 0.0, 1.0);\r\n\t\t#ifdef ADDTIVEFOG\r\n\t\t\tgl_FragColor.rgb = mix(gl_FragColor.rgb, vec3(0.0), lerpFact);\r\n\t\t#else\r\n\t\t\tgl_FragColor.rgb = mix(gl_FragColor.rgb, u_FogColor, lerpFact);\r\n\t\t#endif\r\n\t#endif\r\n\t\r\n}\r\n\r\n";

	var UnlitVS = "#include \"Lighting.glsl\";\r\n\r\nattribute vec4 a_Position;\r\n\r\nattribute vec2 a_Texcoord0;\r\n\r\n#ifdef GPU_INSTANCE\r\n\tattribute mat4 a_MvpMatrix;\r\n#else\r\n\tuniform mat4 u_MvpMatrix;\r\n#endif\r\n\r\nattribute vec4 a_Color;\r\nvarying vec4 v_Color;\r\nvarying vec2 v_Texcoord0;\r\n\r\n#ifdef TILINGOFFSET\r\n\tuniform vec4 u_TilingOffset;\r\n#endif\r\n\r\n#ifdef BONE\r\n\tconst int c_MaxBoneCount = 24;\r\n\tattribute vec4 a_BoneIndices;\r\n\tattribute vec4 a_BoneWeights;\r\n\tuniform mat4 u_Bones[c_MaxBoneCount];\r\n#endif\r\n\r\nvoid main() {\r\n\tvec4 position;\r\n\t#ifdef BONE\r\n\t\tmat4 skinTransform = u_Bones[int(a_BoneIndices.x)] * a_BoneWeights.x;\r\n\t\tskinTransform += u_Bones[int(a_BoneIndices.y)] * a_BoneWeights.y;\r\n\t\tskinTransform += u_Bones[int(a_BoneIndices.z)] * a_BoneWeights.z;\r\n\t\tskinTransform += u_Bones[int(a_BoneIndices.w)] * a_BoneWeights.w;\r\n\t\tposition=skinTransform*a_Position;\r\n\t#else\r\n\t\tposition=a_Position;\r\n\t#endif\r\n\t#ifdef GPU_INSTANCE\r\n\t\tgl_Position = a_MvpMatrix * position;\r\n\t#else\r\n\t\tgl_Position = u_MvpMatrix * position;\r\n\t#endif\r\n\r\n\t#ifdef TILINGOFFSET\r\n\t\tv_Texcoord0=TransformUV(a_Texcoord0,u_TilingOffset);\r\n\t#else\r\n\t\tv_Texcoord0=a_Texcoord0;\r\n\t#endif\r\n\r\n\t#if defined(COLOR)&&defined(ENABLEVERTEXCOLOR)\r\n\t\tv_Color = a_Color;\r\n\t#endif\r\n\tgl_Position=remapGLPositionZ(gl_Position);\r\n}";

	var WaterPrimaryPS = "#ifdef HIGHPRECISION\r\n\tprecision highp float;\r\n#else\r\n\tprecision mediump float;\r\n#endif\r\n\r\n#ifdef MAINTEXTURE\r\n\tuniform sampler2D u_MainTexture;\r\n#endif\r\n\r\n#ifdef NORMALTEXTURE\r\n\tuniform sampler2D u_NormalTexture;\r\n#endif\r\n\r\nuniform vec4 u_HorizonColor;\r\n\r\nvarying vec3 v_Normal;\r\nvarying vec3 v_Tangent;\r\nvarying vec3 v_Binormal;\r\nvarying vec3 v_ViewDir;\r\nvarying vec2 v_Texcoord0;\r\nvarying vec2 v_Texcoord1;\r\n\r\n#include \"Lighting.glsl\"\r\n\r\nvoid main()\r\n{\r\n\tvec4 bumpColor1 = texture2D(u_NormalTexture, v_Texcoord0);\r\n\tvec4 bumpColor2 = texture2D(u_NormalTexture, v_Texcoord1);\r\n\t\r\n\tvec3 normal1 = NormalSampleToWorldSpace1(bumpColor1, v_Tangent, v_Binormal, v_Normal);\r\n\tvec3 normal2 = NormalSampleToWorldSpace1(bumpColor2, v_Tangent, v_Binormal, v_Normal);\r\n\t\r\n\tvec3 normal = normalize((normal1 + normal2) * 0.5);\r\n\tvec3 viewDir = normalize(v_ViewDir);\r\n\tfloat fresnel = dot(viewDir, normal);\r\n\t\r\n\tvec4 waterColor = texture2D(u_MainTexture, vec2(fresnel, fresnel));\r\n\t\r\n\tvec4 color;\r\n\tcolor.rgb = mix(waterColor.rgb, u_HorizonColor.rgb, vec3(waterColor.a));\r\n\tcolor.a = u_HorizonColor.a;\r\n\t\r\n\tgl_FragColor = color;\r\n}\r\n\r\n";

	var WaterPrimaryVS = "#include \"Lighting.glsl\";\r\n\r\nattribute vec4 a_Position;\r\nattribute vec3 a_Normal;\r\nattribute vec4 a_Tangent0;\r\n\r\nuniform mat4 u_MvpMatrix;\r\nuniform mat4 u_WorldMat;\r\nuniform vec3 u_CameraPos;\r\nuniform float u_WaveScale;\r\nuniform vec4 u_WaveSpeed;\r\nuniform float u_Time;\r\n\r\nvarying vec3 v_Normal;\r\nvarying vec3 v_Tangent;\r\nvarying vec3 v_Binormal;\r\nvarying vec3 v_ViewDir;\r\nvarying vec2 v_Texcoord0;\r\nvarying vec2 v_Texcoord1;\r\n\r\nvoid main()\r\n{\r\n\tvec4 positionWorld = u_WorldMat * a_Position;\r\n\tvec4 position = u_MvpMatrix * a_Position;\r\n\t\r\n\tvec4 temp = vec4(positionWorld.x, positionWorld.z, positionWorld.x, positionWorld.z) * u_WaveScale + u_WaveSpeed * u_WaveScale * u_Time;\r\n\t\r\n\tv_Texcoord0 = temp.xy * vec2(0.4, 0.45);\r\n\tv_Texcoord1 = temp.wz;\r\n\t\r\n\tmat3 worldMat = mat3(u_WorldMat);\r\n\tv_Normal = worldMat * a_Normal;\r\n\tv_Tangent = worldMat * a_Tangent0.xyz;\r\n\tv_Binormal = cross(v_Normal, v_Tangent) * a_Tangent0.w;\r\n\t\r\n\tv_ViewDir = u_CameraPos - positionWorld.xyz;\r\n\tgl_Position = position;\r\n\tgl_Position=remapGLPositionZ(gl_Position);\r\n}";

	class ShaderVariable {
	    constructor() {
	        this.textureID = -1;
	    }
	}

	class ShaderInstance extends Laya.Resource {
	    constructor(vs, ps, attributeMap, uniformMap, shaderPass) {
	        super();
	        this._stateParamsMap = [];
	        this._uploadMark = -1;
	        this._uploadRenderType = -1;
	        this._vs = vs;
	        this._ps = ps;
	        this._attributeMap = attributeMap;
	        this._uniformMap = uniformMap;
	        this._shaderPass = shaderPass;
	        this._create();
	        this.lock = true;
	    }
	    _create() {
	        var gl = Laya.LayaGL.instance;
	        this._program = gl.createProgram();
	        this._vshader = this._createShader(gl, this._vs, gl.VERTEX_SHADER);
	        this._pshader = this._createShader(gl, this._ps, gl.FRAGMENT_SHADER);
	        gl.attachShader(this._program, this._vshader);
	        gl.attachShader(this._program, this._pshader);
	        for (var k in this._attributeMap)
	            gl.bindAttribLocation(this._program, this._attributeMap[k], k);
	        gl.linkProgram(this._program);
	        if (!Laya.Render.isConchApp && Shader3D.debugMode && !gl.getProgramParameter(this._program, gl.LINK_STATUS))
	            throw gl.getProgramInfoLog(this._program);
	        var sceneParms = [];
	        var cameraParms = [];
	        var spriteParms = [];
	        var materialParms = [];
	        var customParms = [];
	        this._customUniformParamsMap = [];
	        var nUniformNum = gl.getProgramParameter(this._program, gl.ACTIVE_UNIFORMS);
	        Laya.WebGLContext.useProgram(gl, this._program);
	        this._curActTexIndex = 0;
	        var one, i, n;
	        for (i = 0; i < nUniformNum; i++) {
	            var uniformData = gl.getActiveUniform(this._program, i);
	            var uniName = uniformData.name;
	            one = new ShaderVariable();
	            one.location = gl.getUniformLocation(this._program, uniName);
	            if (uniName.indexOf('[0]') > 0) {
	                one.name = uniName = uniName.substr(0, uniName.length - 3);
	                one.isArray = true;
	            }
	            else {
	                one.name = uniName;
	                one.isArray = false;
	            }
	            one.type = uniformData.type;
	            this._addShaderUnifiormFun(one);
	            var uniformPeriod = this._uniformMap[uniName];
	            if (uniformPeriod != null) {
	                one.dataOffset = Shader3D.propertyNameToID(uniName);
	                switch (uniformPeriod) {
	                    case Shader3D.PERIOD_CUSTOM:
	                        customParms.push(one);
	                        break;
	                    case Shader3D.PERIOD_MATERIAL:
	                        materialParms.push(one);
	                        break;
	                    case Shader3D.PERIOD_SPRITE:
	                        spriteParms.push(one);
	                        break;
	                    case Shader3D.PERIOD_CAMERA:
	                        cameraParms.push(one);
	                        break;
	                    case Shader3D.PERIOD_SCENE:
	                        sceneParms.push(one);
	                        break;
	                    default:
	                        throw new Error("Shader3D: period is unkonw.");
	                }
	            }
	        }
	        this._sceneUniformParamsMap = Laya.LayaGL.instance.createCommandEncoder(sceneParms.length * 4 * 5 + 4, 64, true);
	        for (i = 0, n = sceneParms.length; i < n; i++)
	            this._sceneUniformParamsMap.addShaderUniform(sceneParms[i]);
	        this._cameraUniformParamsMap = Laya.LayaGL.instance.createCommandEncoder(cameraParms.length * 4 * 5 + 4, 64, true);
	        for (i = 0, n = cameraParms.length; i < n; i++)
	            this._cameraUniformParamsMap.addShaderUniform(cameraParms[i]);
	        this._spriteUniformParamsMap = Laya.LayaGL.instance.createCommandEncoder(spriteParms.length * 4 * 5 + 4, 64, true);
	        for (i = 0, n = spriteParms.length; i < n; i++)
	            this._spriteUniformParamsMap.addShaderUniform(spriteParms[i]);
	        this._materialUniformParamsMap = Laya.LayaGL.instance.createCommandEncoder(materialParms.length * 4 * 5 + 4, 64, true);
	        for (i = 0, n = materialParms.length; i < n; i++)
	            this._materialUniformParamsMap.addShaderUniform(materialParms[i]);
	        this._customUniformParamsMap.length = customParms.length;
	        for (i = 0, n = customParms.length; i < n; i++) {
	            var custom = customParms[i];
	            this._customUniformParamsMap[custom.dataOffset] = custom;
	        }
	        var stateMap = this._shaderPass._stateMap;
	        for (var s in stateMap)
	            this._stateParamsMap[stateMap[s]] = Shader3D.propertyNameToID(s);
	    }
	    _getRenderState(shaderDatas, stateIndex) {
	        var stateID = this._stateParamsMap[stateIndex];
	        if (stateID == null)
	            return null;
	        else
	            return shaderDatas[stateID];
	    }
	    _disposeResource() {
	        Laya.LayaGL.instance.deleteShader(this._vshader);
	        Laya.LayaGL.instance.deleteShader(this._pshader);
	        Laya.LayaGL.instance.deleteProgram(this._program);
	        this._vshader = this._pshader = this._program = null;
	        this._setGPUMemory(0);
	        this._curActTexIndex = 0;
	    }
	    _addShaderUnifiormFun(one) {
	        var gl = Laya.LayaGL.instance;
	        one.caller = this;
	        var isArray = one.isArray;
	        switch (one.type) {
	            case gl.BOOL:
	                one.fun = this._uniform1i;
	                one.uploadedValue = new Array(1);
	                break;
	            case gl.INT:
	                one.fun = isArray ? this._uniform1iv : this._uniform1i;
	                one.uploadedValue = new Array(1);
	                break;
	            case gl.FLOAT:
	                one.fun = isArray ? this._uniform1fv : this._uniform1f;
	                one.uploadedValue = new Array(1);
	                break;
	            case gl.FLOAT_VEC2:
	                one.fun = isArray ? this._uniform_vec2v : this._uniform_vec2;
	                one.uploadedValue = new Array(2);
	                break;
	            case gl.FLOAT_VEC3:
	                one.fun = isArray ? this._uniform_vec3v : this._uniform_vec3;
	                one.uploadedValue = new Array(3);
	                break;
	            case gl.FLOAT_VEC4:
	                one.fun = isArray ? this._uniform_vec4v : this._uniform_vec4;
	                one.uploadedValue = new Array(4);
	                break;
	            case gl.FLOAT_MAT2:
	                one.fun = this._uniformMatrix2fv;
	                break;
	            case gl.FLOAT_MAT3:
	                one.fun = this._uniformMatrix3fv;
	                break;
	            case gl.FLOAT_MAT4:
	                one.fun = isArray ? this._uniformMatrix4fv : this._uniformMatrix4f;
	                break;
	            case gl.SAMPLER_2D:
	                gl.uniform1i(one.location, this._curActTexIndex);
	                one.textureID = Laya.WebGLContext._glTextureIDs[this._curActTexIndex++];
	                one.fun = this._uniform_sampler2D;
	                break;
	            case 0x8b5f:
	                gl.uniform1i(one.location, this._curActTexIndex);
	                one.textureID = Laya.WebGLContext._glTextureIDs[this._curActTexIndex++];
	                one.fun = this._uniform_sampler3D;
	                break;
	            case gl.SAMPLER_CUBE:
	                gl.uniform1i(one.location, this._curActTexIndex);
	                one.textureID = Laya.WebGLContext._glTextureIDs[this._curActTexIndex++];
	                one.fun = this._uniform_samplerCube;
	                break;
	            default:
	                throw new Error("compile shader err!");
	                break;
	        }
	    }
	    _createShader(gl, str, type) {
	        var shader = gl.createShader(type);
	        gl.shaderSource(shader, str);
	        gl.compileShader(shader);
	        if (Shader3D.debugMode && !gl.getShaderParameter(shader, gl.COMPILE_STATUS))
	            throw gl.getShaderInfoLog(shader);
	        return shader;
	    }
	    _uniform1f(one, value) {
	        var uploadedValue = one.uploadedValue;
	        if (uploadedValue[0] !== value) {
	            Laya.LayaGL.instance.uniform1f(one.location, uploadedValue[0] = value);
	            return 1;
	        }
	        return 0;
	    }
	    _uniform1fv(one, value) {
	        if (value.length < 4) {
	            var uploadedValue = one.uploadedValue;
	            if (uploadedValue[0] !== value[0] || uploadedValue[1] !== value[1] || uploadedValue[2] !== value[2] || uploadedValue[3] !== value[3]) {
	                Laya.LayaGL.instance.uniform1fv(one.location, value);
	                uploadedValue[0] = value[0];
	                uploadedValue[1] = value[1];
	                uploadedValue[2] = value[2];
	                uploadedValue[3] = value[3];
	                return 1;
	            }
	            return 0;
	        }
	        else {
	            Laya.LayaGL.instance.uniform1fv(one.location, value);
	            return 1;
	        }
	    }
	    _uniform_vec2(one, v) {
	        var uploadedValue = one.uploadedValue;
	        if (uploadedValue[0] !== v.x || uploadedValue[1] !== v.y) {
	            Laya.LayaGL.instance.uniform2f(one.location, uploadedValue[0] = v.x, uploadedValue[1] = v.y);
	            return 1;
	        }
	        return 0;
	    }
	    _uniform_vec2v(one, value) {
	        if (value.length < 2) {
	            var uploadedValue = one.uploadedValue;
	            if (uploadedValue[0] !== value[0] || uploadedValue[1] !== value[1] || uploadedValue[2] !== value[2] || uploadedValue[3] !== value[3]) {
	                Laya.LayaGL.instance.uniform2fv(one.location, value);
	                uploadedValue[0] = value[0];
	                uploadedValue[1] = value[1];
	                uploadedValue[2] = value[2];
	                uploadedValue[3] = value[3];
	                return 1;
	            }
	            return 0;
	        }
	        else {
	            Laya.LayaGL.instance.uniform2fv(one.location, value);
	            return 1;
	        }
	    }
	    _uniform_vec3(one, v) {
	        var uploadedValue = one.uploadedValue;
	        if (uploadedValue[0] !== v.x || uploadedValue[1] !== v.y || uploadedValue[2] !== v.z) {
	            Laya.LayaGL.instance.uniform3f(one.location, uploadedValue[0] = v.x, uploadedValue[1] = v.y, uploadedValue[2] = v.z);
	            return 1;
	        }
	        return 0;
	    }
	    _uniform_vec3v(one, v) {
	        Laya.LayaGL.instance.uniform3fv(one.location, v);
	        return 1;
	    }
	    _uniform_vec4(one, v) {
	        var uploadedValue = one.uploadedValue;
	        if (uploadedValue[0] !== v.x || uploadedValue[1] !== v.y || uploadedValue[2] !== v.z || uploadedValue[3] !== v.w) {
	            Laya.LayaGL.instance.uniform4f(one.location, uploadedValue[0] = v.x, uploadedValue[1] = v.y, uploadedValue[2] = v.z, uploadedValue[3] = v.w);
	            return 1;
	        }
	        return 0;
	    }
	    _uniform_vec4v(one, v) {
	        Laya.LayaGL.instance.uniform4fv(one.location, v);
	        return 1;
	    }
	    _uniformMatrix2fv(one, value) {
	        Laya.LayaGL.instance.uniformMatrix2fv(one.location, false, value);
	        return 1;
	    }
	    _uniformMatrix3fv(one, value) {
	        Laya.LayaGL.instance.uniformMatrix3fv(one.location, false, value);
	        return 1;
	    }
	    _uniformMatrix4f(one, m) {
	        var value = m.elements;
	        Laya.LayaGL.instance.uniformMatrix4fv(one.location, false, value);
	        return 1;
	    }
	    _uniformMatrix4fv(one, m) {
	        Laya.LayaGL.instance.uniformMatrix4fv(one.location, false, m);
	        return 1;
	    }
	    _uniform1i(one, value) {
	        var uploadedValue = one.uploadedValue;
	        if (uploadedValue[0] !== value) {
	            Laya.LayaGL.instance.uniform1i(one.location, uploadedValue[0] = value);
	            return 1;
	        }
	        return 0;
	    }
	    _uniform1iv(one, value) {
	        Laya.LayaGL.instance.uniform1iv(one.location, value);
	        return 1;
	    }
	    _uniform_ivec2(one, value) {
	        var uploadedValue = one.uploadedValue;
	        if (uploadedValue[0] !== value[0] || uploadedValue[1] !== value[1]) {
	            Laya.LayaGL.instance.uniform2i(one.location, uploadedValue[0] = value[0], uploadedValue[1] = value[1]);
	            return 1;
	        }
	        return 0;
	    }
	    _uniform_ivec2v(one, value) {
	        Laya.LayaGL.instance.uniform2iv(one.location, value);
	        return 1;
	    }
	    _uniform_vec3i(one, value) {
	        var uploadedValue = one.uploadedValue;
	        if (uploadedValue[0] !== value[0] || uploadedValue[1] !== value[1] || uploadedValue[2] !== value[2]) {
	            Laya.LayaGL.instance.uniform3i(one.location, uploadedValue[0] = value[0], uploadedValue[1] = value[1], uploadedValue[2] = value[2]);
	            return 1;
	        }
	        return 0;
	    }
	    _uniform_vec3vi(one, value) {
	        Laya.LayaGL.instance.uniform3iv(one.location, value);
	        return 1;
	    }
	    _uniform_vec4i(one, value) {
	        var uploadedValue = one.uploadedValue;
	        if (uploadedValue[0] !== value[0] || uploadedValue[1] !== value[1] || uploadedValue[2] !== value[2] || uploadedValue[3] !== value[3]) {
	            Laya.LayaGL.instance.uniform4i(one.location, uploadedValue[0] = value[0], uploadedValue[1] = value[1], uploadedValue[2] = value[2], uploadedValue[3] = value[3]);
	            return 1;
	        }
	        return 0;
	    }
	    _uniform_vec4vi(one, value) {
	        Laya.LayaGL.instance.uniform4iv(one.location, value);
	        return 1;
	    }
	    _uniform_sampler2D(one, texture) {
	        var value = texture._getSource() || texture.defaulteTexture._getSource();
	        var gl = Laya.LayaGL.instance;
	        Laya.WebGLContext.activeTexture(gl, one.textureID);
	        Laya.WebGLContext.bindTexture(gl, gl.TEXTURE_2D, value);
	        return 0;
	    }
	    _uniform_sampler3D(one, texture) {
	        var value = texture._getSource() || texture.defaulteTexture._getSource();
	        var gl = Laya.LayaGL.instance;
	        Laya.WebGLContext.activeTexture(gl, one.textureID);
	        Laya.WebGLContext.bindTexture(gl, WebGL2RenderingContext.TEXTURE_3D, value);
	        return 0;
	    }
	    _uniform_samplerCube(one, texture) {
	        var value = texture._getSource() || texture.defaulteTexture._getSource();
	        var gl = Laya.LayaGL.instance;
	        Laya.WebGLContext.activeTexture(gl, one.textureID);
	        Laya.WebGLContext.bindTexture(gl, gl.TEXTURE_CUBE_MAP, value);
	        return 0;
	    }
	    bind() {
	        return Laya.WebGLContext.useProgram(Laya.LayaGL.instance, this._program);
	    }
	    uploadUniforms(shaderUniform, shaderDatas, uploadUnTexture) {
	        Laya.Stat.shaderCall += Laya.LayaGLRunner.uploadShaderUniforms(Laya.LayaGL.instance, shaderUniform, shaderDatas, uploadUnTexture);
	    }
	    uploadRenderStateBlendDepth(shaderDatas) {
	        var gl = Laya.LayaGL.instance;
	        var renderState = this._shaderPass.renderState;
	        var datas = shaderDatas.getData();
	        var depthWrite = this._getRenderState(datas, Shader3D.RENDER_STATE_DEPTH_WRITE);
	        var depthTest = this._getRenderState(datas, Shader3D.RENDER_STATE_DEPTH_TEST);
	        var blend = this._getRenderState(datas, Shader3D.RENDER_STATE_BLEND);
	        depthWrite == null && (depthWrite = renderState.depthWrite);
	        depthTest == null && (depthTest = renderState.depthTest);
	        blend == null && (blend = renderState.blend);
	        Laya.WebGLContext.setDepthMask(gl, depthWrite);
	        if (depthTest === RenderState.DEPTHTEST_OFF)
	            Laya.WebGLContext.setDepthTest(gl, false);
	        else {
	            Laya.WebGLContext.setDepthTest(gl, true);
	            Laya.WebGLContext.setDepthFunc(gl, depthTest);
	        }
	        switch (blend) {
	            case RenderState.BLEND_DISABLE:
	                Laya.WebGLContext.setBlend(gl, false);
	                break;
	            case RenderState.BLEND_ENABLE_ALL:
	                var blendEquation = this._getRenderState(datas, Shader3D.RENDER_STATE_BLEND_EQUATION);
	                var srcBlend = this._getRenderState(datas, Shader3D.RENDER_STATE_BLEND_SRC);
	                var dstBlend = this._getRenderState(datas, Shader3D.RENDER_STATE_BLEND_DST);
	                blendEquation == null && (blendEquation = renderState.blendEquation);
	                srcBlend == null && (srcBlend = renderState.srcBlend);
	                dstBlend == null && (dstBlend = renderState.dstBlend);
	                Laya.WebGLContext.setBlend(gl, true);
	                Laya.WebGLContext.setBlendEquation(gl, blendEquation);
	                Laya.WebGLContext.setBlendFunc(gl, srcBlend, dstBlend);
	                break;
	            case RenderState.BLEND_ENABLE_SEPERATE:
	                var blendEquationRGB = this._getRenderState(datas, Shader3D.RENDER_STATE_BLEND_EQUATION_RGB);
	                var blendEquationAlpha = this._getRenderState(datas, Shader3D.RENDER_STATE_BLEND_EQUATION_ALPHA);
	                var srcRGB = this._getRenderState(datas, Shader3D.RENDER_STATE_BLEND_SRC_RGB);
	                var dstRGB = this._getRenderState(datas, Shader3D.RENDER_STATE_BLEND_DST_RGB);
	                var srcAlpha = this._getRenderState(datas, Shader3D.RENDER_STATE_BLEND_SRC_ALPHA);
	                var dstAlpha = this._getRenderState(datas, Shader3D.RENDER_STATE_BLEND_DST_ALPHA);
	                blendEquationRGB == null && (blendEquationRGB = renderState.blendEquationRGB);
	                blendEquationAlpha == null && (blendEquationAlpha = renderState.blendEquationAlpha);
	                srcRGB == null && (srcRGB = renderState.srcBlendRGB);
	                dstRGB == null && (dstRGB = renderState.dstBlendRGB);
	                srcAlpha == null && (srcAlpha = renderState.srcBlendAlpha);
	                dstAlpha == null && (dstAlpha = renderState.dstBlendAlpha);
	                Laya.WebGLContext.setBlend(gl, true);
	                Laya.WebGLContext.setBlendEquationSeparate(gl, blendEquationRGB, blendEquationAlpha);
	                Laya.WebGLContext.setBlendFuncSeperate(gl, srcRGB, dstRGB, srcAlpha, dstAlpha);
	                break;
	        }
	    }
	    uploadRenderStateFrontFace(shaderDatas, isTarget, invertFront) {
	        var gl = Laya.LayaGL.instance;
	        var renderState = this._shaderPass.renderState;
	        var datas = shaderDatas.getData();
	        var cull = this._getRenderState(datas, Shader3D.RENDER_STATE_CULL);
	        cull == null && (cull = renderState.cull);
	        var forntFace;
	        switch (cull) {
	            case RenderState.CULL_NONE:
	                Laya.WebGLContext.setCullFace(gl, false);
	                break;
	            case RenderState.CULL_FRONT:
	                Laya.WebGLContext.setCullFace(gl, true);
	                if (isTarget) {
	                    if (invertFront)
	                        forntFace = gl.CCW;
	                    else
	                        forntFace = gl.CW;
	                }
	                else {
	                    if (invertFront)
	                        forntFace = gl.CW;
	                    else
	                        forntFace = gl.CCW;
	                }
	                Laya.WebGLContext.setFrontFace(gl, forntFace);
	                break;
	            case RenderState.CULL_BACK:
	                Laya.WebGLContext.setCullFace(gl, true);
	                if (isTarget) {
	                    if (invertFront)
	                        forntFace = gl.CW;
	                    else
	                        forntFace = gl.CCW;
	                }
	                else {
	                    if (invertFront)
	                        forntFace = gl.CCW;
	                    else
	                        forntFace = gl.CW;
	                }
	                Laya.WebGLContext.setFrontFace(gl, forntFace);
	                break;
	        }
	    }
	    uploadCustomUniform(index, data) {
	        Laya.Stat.shaderCall += Laya.LayaGLRunner.uploadCustomUniform(Laya.LayaGL.instance, this._customUniformParamsMap, index, data);
	    }
	    _uniformMatrix2fvForNative(one, value) {
	        Laya.LayaGL.instance.uniformMatrix2fvEx(one.location, false, value);
	        return 1;
	    }
	    _uniformMatrix3fvForNative(one, value) {
	        Laya.LayaGL.instance.uniformMatrix3fvEx(one.location, false, value);
	        return 1;
	    }
	    _uniformMatrix4fvForNative(one, m) {
	        Laya.LayaGL.instance.uniformMatrix4fvEx(one.location, false, m);
	        return 1;
	    }
	}

	class ShaderPass extends Laya.ShaderCompile {
	    constructor(owner, vs, ps, stateMap) {
	        super(vs, ps, null);
	        this._cacheSharders = {};
	        this._cacheShaderHierarchy = 1;
	        this._renderState = new RenderState();
	        this._validDefine = new DefineDatas();
	        this._owner = owner;
	        this._stateMap = stateMap;
	        for (var k in this.defs)
	            this._validDefine.add(Shader3D.getDefineByName(k));
	    }
	    get renderState() {
	        return this._renderState;
	    }
	    _compileToTree(parent, lines, start, includefiles, defs) {
	        var node, preNode;
	        var text, name, fname;
	        var ofs, words, noUseNode;
	        var i, n, j;
	        for (i = start; i < lines.length; i++) {
	            text = lines[i];
	            if (text.length < 1)
	                continue;
	            ofs = text.indexOf("//");
	            if (ofs === 0)
	                continue;
	            if (ofs >= 0)
	                text = text.substr(0, ofs);
	            node = noUseNode || new Laya.ShaderNode(includefiles);
	            noUseNode = null;
	            node.text = text;
	            if ((ofs = text.indexOf("#")) >= 0) {
	                name = "#";
	                for (j = ofs + 1, n = text.length; j < n; j++) {
	                    var c = text.charAt(j);
	                    if (c === ' ' || c === '\t' || c === '?')
	                        break;
	                    name += c;
	                }
	                node.name = name;
	                switch (name) {
	                    case "#ifdef":
	                    case "#ifndef":
	                        node.setParent(parent);
	                        parent = node;
	                        if (defs) {
	                            words = text.substr(j).split(Laya.ShaderCompile._splitToWordExps3);
	                            for (j = 0; j < words.length; j++) {
	                                text = words[j];
	                                text.length && (defs[text] = true);
	                            }
	                        }
	                        continue;
	                    case "#if":
	                    case "#elif":
	                        node.setParent(parent);
	                        parent = node;
	                        if (defs) {
	                            words = text.substr(j).split(Laya.ShaderCompile._splitToWordExps3);
	                            for (j = 0; j < words.length; j++) {
	                                text = words[j];
	                                text.length && text != "defined" && (defs[text] = true);
	                            }
	                        }
	                        continue;
	                    case "#else":
	                        parent = parent.parent;
	                        preNode = parent.childs[parent.childs.length - 1];
	                        node.setParent(parent);
	                        parent = node;
	                        continue;
	                    case "#endif":
	                        parent = parent.parent;
	                        preNode = parent.childs[parent.childs.length - 1];
	                        node.setParent(parent);
	                        continue;
	                    case "#include":
	                        words = Laya.ShaderCompile.splitToWords(text, null);
	                        var inlcudeFile = Laya.ShaderCompile.includes[words[1]];
	                        if (!inlcudeFile) {
	                            throw "ShaderCompile error no this include file:" + words[1];
	                        }
	                        if ((ofs = words[0].indexOf("?")) < 0) {
	                            node.setParent(parent);
	                            text = inlcudeFile.getWith(words[2] == 'with' ? words[3] : null);
	                            this._compileToTree(node, text.split('\n'), 0, includefiles, defs);
	                            node.text = "";
	                            continue;
	                        }
	                        node.setCondition(words[0].substr(ofs + 1), Laya.ShaderCompile.IFDEF_YES);
	                        node.text = inlcudeFile.getWith(words[2] == 'with' ? words[3] : null);
	                        break;
	                    case "#import":
	                        words = Laya.ShaderCompile.splitToWords(text, null);
	                        fname = words[1];
	                        includefiles.push({ node: node, file: Laya.ShaderCompile.includes[fname], ofs: node.text.length });
	                        continue;
	                }
	            }
	            else {
	                preNode = parent.childs[parent.childs.length - 1];
	                if (preNode && !preNode.name) {
	                    includefiles.length > 0 && Laya.ShaderCompile.splitToWords(text, preNode);
	                    noUseNode = node;
	                    preNode.text += "\n" + text;
	                    continue;
	                }
	                includefiles.length > 0 && Laya.ShaderCompile.splitToWords(text, node);
	            }
	            node.setParent(parent);
	        }
	    }
	    _resizeCacheShaderMap(cacheMap, hierarchy, resizeLength) {
	        var end = this._cacheShaderHierarchy - 1;
	        if (hierarchy == end) {
	            for (var k in cacheMap) {
	                var shader = cacheMap[k];
	                for (var i = 0, n = resizeLength - end; i < n; i++) {
	                    if (i == n - 1)
	                        cacheMap[0] = shader;
	                    else
	                        cacheMap = cacheMap[i == 0 ? k : 0] = {};
	                }
	            }
	            this._cacheShaderHierarchy = resizeLength;
	        }
	        else {
	            for (var k in cacheMap)
	                this._resizeCacheShaderMap(cacheMap[k], ++hierarchy, resizeLength);
	        }
	    }
	    withCompile(compileDefine) {
	        compileDefine._intersectionDefineDatas(this._validDefine);
	        var cacheShaders = this._cacheSharders;
	        var maskLength = compileDefine._length;
	        if (maskLength > this._cacheShaderHierarchy) {
	            this._resizeCacheShaderMap(cacheShaders, 0, maskLength);
	            this._cacheShaderHierarchy = maskLength;
	        }
	        var mask = compileDefine._mask;
	        var endIndex = compileDefine._length - 1;
	        var maxEndIndex = this._cacheShaderHierarchy - 1;
	        for (var i = 0; i < maxEndIndex; i++) {
	            var subMask = endIndex < i ? 0 : mask[i];
	            var subCacheShaders = cacheShaders[subMask];
	            (subCacheShaders) || (cacheShaders[subMask] = subCacheShaders = {});
	            cacheShaders = subCacheShaders;
	        }
	        var cacheKey = endIndex < maxEndIndex ? 0 : mask[maxEndIndex];
	        var shader = cacheShaders[cacheKey];
	        if (shader)
	            return shader;
	        var defineString = ShaderPass._defineString;
	        Shader3D._getNamesByDefineData(compileDefine, defineString);
	        var config = Config3D._config;
	        var clusterSlices = config.lightClusterCount;
	        var defMap = {};
	        var defineStr = "#define MAX_LIGHT_COUNT " + config.maxLightCount + "\n";
	        defineStr += "#define MAX_LIGHT_COUNT_PER_CLUSTER " + config._maxAreaLightCountPerClusterAverage + "\n";
	        defineStr += "#define CLUSTER_X_COUNT " + clusterSlices.x + "\n";
	        defineStr += "#define CLUSTER_Y_COUNT " + clusterSlices.y + "\n";
	        defineStr += "#define CLUSTER_Z_COUNT " + clusterSlices.z + "\n";
	        for (var i = 0, n = defineString.length; i < n; i++) {
	            var def = defineString[i];
	            defineStr += "#define " + def + "\n";
	            defMap[def] = true;
	        }
	        var vs = this._VS.toscript(defMap, []);
	        var vsVersion = '';
	        if (vs[0].indexOf('#version') == 0) {
	            vsVersion = vs[0] + '\n';
	            vs.shift();
	        }
	        var ps = this._PS.toscript(defMap, []);
	        var psVersion = '';
	        if (ps[0].indexOf('#version') == 0) {
	            psVersion = ps[0] + '\n';
	            ps.shift();
	        }
	        shader = new ShaderInstance(vsVersion + defineStr + vs.join('\n'), psVersion + defineStr + ps.join('\n'), this._owner._attributeMap || this._owner._owner._attributeMap, this._owner._uniformMap || this._owner._owner._uniformMap, this);
	        cacheShaders[cacheKey] = shader;
	        if (Shader3D.debugMode) {
	            var defStr = "";
	            var defMask = "";
	            if (Laya.WebGL.shaderHighPrecision) {
	                compileDefine.remove(Shader3D.SHADERDEFINE_HIGHPRECISION);
	                var index = defineString.indexOf("HIGHPRECISION");
	                (index !== -1) && (defineString.splice(index, 1));
	            }
	            if (!config._multiLighting) {
	                compileDefine.remove(Shader3D.SHADERDEFINE_LEGACYSINGALLIGHTING);
	                var index = defineString.indexOf("LEGACYSINGLELIGHTING");
	                (index !== -1) && (defineString.splice(index, 1));
	            }
	            for (var i = 0, n = compileDefine._length; i < n; i++)
	                (i == n - 1) ? defMask += mask[i] : defMask += mask[i] + ",";
	            for (var i = 0, n = defineString.length; i < n; i++)
	                (i == n - 1) ? defStr += defineString[i] : defStr += defineString[i] + ",";
	            console.log("%cLayaAir: Shader Compile Information---ShaderName:" + this._owner._owner._name + " SubShaderIndex:" + this._owner._owner._subShaders.indexOf(this._owner) + " PassIndex:" + this._owner._passes.indexOf(this) + " DefineMask:[" + defMask + "]" + " DefineNames:[" + defStr + "]", "color:green");
	        }
	        return shader;
	    }
	}
	ShaderPass._defineString = [];

	class SubShader {
	    constructor(attributeMap, uniformMap) {
	        this._flags = {};
	        this._passes = [];
	        this._attributeMap = attributeMap;
	        this._uniformMap = uniformMap;
	    }
	    setFlag(key, value) {
	        if (value)
	            this._flags[key] = value;
	        else
	            delete this._flags[key];
	    }
	    getFlag(key) {
	        return this._flags[key];
	    }
	    addShaderPass(vs, ps, stateMap = null) {
	        var shaderPass = new ShaderPass(this, vs, ps, stateMap);
	        this._passes.push(shaderPass);
	        return shaderPass;
	    }
	}

	class ShaderInit3D {
	    constructor() {
	    }
	    static __init__() {
	        Shader3D.SHADERDEFINE_HIGHPRECISION = Shader3D.getDefineByName("HIGHPRECISION");
	        Shader3D.SHADERDEFINE_LEGACYSINGALLIGHTING = Shader3D.getDefineByName("LEGACYSINGLELIGHTING");
	        Shader3D.addInclude("Lighting.glsl", LightingGLSL);
	        Shader3D.addInclude("ShadowHelper.glsl", ShadowHelperGLSL);
	        Shader3D.addInclude("BRDF.glsl", BRDFGLSL);
	        Shader3D.addInclude("PBRUtils.glsl", PBRUtilsGLSL);
	        Shader3D.addInclude("PBRStandardLighting.glsl", PBRStandardLightingGLSL);
	        Shader3D.addInclude("PBRSpecularLighting.glsl", PBRSpecularLightingGLSL);
	        Shader3D.addInclude("Colors.glsl", ColorsGLSL);
	        Shader3D.addInclude("Sampling.glsl", SamplingGLSL);
	        Shader3D.addInclude("StdLib.glsl", StdLibGLSL);
	        var attributeMap = {
	            'a_Position': VertexMesh.MESH_POSITION0,
	            'a_Color': VertexMesh.MESH_COLOR0,
	            'a_Normal': VertexMesh.MESH_NORMAL0,
	            'a_Texcoord0': VertexMesh.MESH_TEXTURECOORDINATE0,
	            'a_Texcoord1': VertexMesh.MESH_TEXTURECOORDINATE1,
	            'a_BoneWeights': VertexMesh.MESH_BLENDWEIGHT0,
	            'a_BoneIndices': VertexMesh.MESH_BLENDINDICES0,
	            'a_Tangent0': VertexMesh.MESH_TANGENT0,
	            'a_MvpMatrix': VertexMesh.MESH_MVPMATRIX_ROW0,
	            'a_WorldMat': VertexMesh.MESH_WORLDMATRIX_ROW0
	        };
	        var uniformMap = {
	            'u_Bones': Shader3D.PERIOD_CUSTOM,
	            'u_DiffuseTexture': Shader3D.PERIOD_MATERIAL,
	            'u_SpecularTexture': Shader3D.PERIOD_MATERIAL,
	            'u_NormalTexture': Shader3D.PERIOD_MATERIAL,
	            'u_AlphaTestValue': Shader3D.PERIOD_MATERIAL,
	            'u_DiffuseColor': Shader3D.PERIOD_MATERIAL,
	            'u_MaterialSpecular': Shader3D.PERIOD_MATERIAL,
	            'u_Shininess': Shader3D.PERIOD_MATERIAL,
	            'u_TilingOffset': Shader3D.PERIOD_MATERIAL,
	            'u_WorldMat': Shader3D.PERIOD_SPRITE,
	            'u_MvpMatrix': Shader3D.PERIOD_SPRITE,
	            'u_LightmapScaleOffset': Shader3D.PERIOD_SPRITE,
	            'u_LightMap': Shader3D.PERIOD_SPRITE,
	            'u_CameraPos': Shader3D.PERIOD_CAMERA,
	            'u_Viewport': Shader3D.PERIOD_CAMERA,
	            'u_ProjectionParams': Shader3D.PERIOD_CAMERA,
	            'u_View': Shader3D.PERIOD_CAMERA,
	            'u_ReflectTexture': Shader3D.PERIOD_SCENE,
	            'u_ReflectIntensity': Shader3D.PERIOD_SCENE,
	            'u_FogStart': Shader3D.PERIOD_SCENE,
	            'u_FogRange': Shader3D.PERIOD_SCENE,
	            'u_FogColor': Shader3D.PERIOD_SCENE,
	            'u_DirationLightCount': Shader3D.PERIOD_SCENE,
	            'u_LightBuffer': Shader3D.PERIOD_SCENE,
	            'u_LightClusterBuffer': Shader3D.PERIOD_SCENE,
	            'u_AmbientColor': Shader3D.PERIOD_SCENE,
	            'u_shadowMap1': Shader3D.PERIOD_SCENE,
	            'u_shadowMap2': Shader3D.PERIOD_SCENE,
	            'u_shadowMap3': Shader3D.PERIOD_SCENE,
	            'u_shadowPSSMDistance': Shader3D.PERIOD_SCENE,
	            'u_lightShadowVP': Shader3D.PERIOD_SCENE,
	            'u_shadowPCFoffset': Shader3D.PERIOD_SCENE,
	            'u_DirectionLight.color': Shader3D.PERIOD_SCENE,
	            'u_DirectionLight.direction': Shader3D.PERIOD_SCENE,
	            'u_PointLight.position': Shader3D.PERIOD_SCENE,
	            'u_PointLight.range': Shader3D.PERIOD_SCENE,
	            'u_PointLight.color': Shader3D.PERIOD_SCENE,
	            'u_SpotLight.position': Shader3D.PERIOD_SCENE,
	            'u_SpotLight.direction': Shader3D.PERIOD_SCENE,
	            'u_SpotLight.range': Shader3D.PERIOD_SCENE,
	            'u_SpotLight.spot': Shader3D.PERIOD_SCENE,
	            'u_SpotLight.color': Shader3D.PERIOD_SCENE
	        };
	        var stateMap = {
	            's_Cull': Shader3D.RENDER_STATE_CULL,
	            's_Blend': Shader3D.RENDER_STATE_BLEND,
	            's_BlendSrc': Shader3D.RENDER_STATE_BLEND_SRC,
	            's_BlendDst': Shader3D.RENDER_STATE_BLEND_DST,
	            's_DepthTest': Shader3D.RENDER_STATE_DEPTH_TEST,
	            's_DepthWrite': Shader3D.RENDER_STATE_DEPTH_WRITE
	        };
	        var shader = Shader3D.add("BLINNPHONG", null, null, true);
	        var subShader = new SubShader(attributeMap, uniformMap);
	        shader.addSubShader(subShader);
	        subShader.addShaderPass(MeshBlinnPhongVS, MeshBlinnPhongPS, stateMap);
	        attributeMap = {
	            'a_Position': VertexMesh.MESH_POSITION0,
	            'a_Color': VertexMesh.MESH_COLOR0
	        };
	        uniformMap = {
	            'u_MvpMatrix': Shader3D.PERIOD_SPRITE,
	            'u_Color': Shader3D.PERIOD_MATERIAL
	        };
	        stateMap = {
	            's_Cull': Shader3D.RENDER_STATE_CULL,
	            's_Blend': Shader3D.RENDER_STATE_BLEND,
	            's_BlendSrc': Shader3D.RENDER_STATE_BLEND_SRC,
	            's_BlendDst': Shader3D.RENDER_STATE_BLEND_DST,
	            's_DepthTest': Shader3D.RENDER_STATE_DEPTH_TEST,
	            's_DepthWrite': Shader3D.RENDER_STATE_DEPTH_WRITE
	        };
	        shader = Shader3D.add("LineShader");
	        subShader = new SubShader(attributeMap, uniformMap);
	        shader.addSubShader(subShader);
	        subShader.addShaderPass(lineVS, linePS, stateMap);
	        attributeMap = {
	            'a_Position': VertexMesh.MESH_POSITION0,
	            'a_Normal': VertexMesh.MESH_NORMAL0,
	            'a_Tangent0': VertexMesh.MESH_TANGENT0,
	            'a_Texcoord0': VertexMesh.MESH_TEXTURECOORDINATE0,
	            'a_BoneWeights': VertexMesh.MESH_BLENDWEIGHT0,
	            'a_BoneIndices': VertexMesh.MESH_BLENDINDICES0,
	            'a_MvpMatrix': VertexMesh.MESH_MVPMATRIX_ROW0,
	            'a_WorldMat': VertexMesh.MESH_WORLDMATRIX_ROW0
	        };
	        uniformMap = {
	            'u_Bones': Shader3D.PERIOD_CUSTOM,
	            'u_MvpMatrix': Shader3D.PERIOD_SPRITE,
	            'u_WorldMat': Shader3D.PERIOD_SPRITE,
	            'u_CameraPos': Shader3D.PERIOD_CAMERA,
	            'u_View': Shader3D.PERIOD_CAMERA,
	            'u_ProjectionParams': Shader3D.PERIOD_CAMERA,
	            'u_Viewport': Shader3D.PERIOD_CAMERA,
	            'u_AlphaTestValue': Shader3D.PERIOD_MATERIAL,
	            'u_AlbedoColor': Shader3D.PERIOD_MATERIAL,
	            'u_EmissionColor': Shader3D.PERIOD_MATERIAL,
	            'u_AlbedoTexture': Shader3D.PERIOD_MATERIAL,
	            'u_NormalTexture': Shader3D.PERIOD_MATERIAL,
	            'u_ParallaxTexture': Shader3D.PERIOD_MATERIAL,
	            'u_MetallicGlossTexture': Shader3D.PERIOD_MATERIAL,
	            'u_OcclusionTexture': Shader3D.PERIOD_MATERIAL,
	            'u_EmissionTexture': Shader3D.PERIOD_MATERIAL,
	            'u_metallic': Shader3D.PERIOD_MATERIAL,
	            'u_smoothness': Shader3D.PERIOD_MATERIAL,
	            'u_smoothnessScale': Shader3D.PERIOD_MATERIAL,
	            'u_occlusionStrength': Shader3D.PERIOD_MATERIAL,
	            'u_normalScale': Shader3D.PERIOD_MATERIAL,
	            'u_parallaxScale': Shader3D.PERIOD_MATERIAL,
	            'u_TilingOffset': Shader3D.PERIOD_MATERIAL,
	            'u_ReflectTexture': Shader3D.PERIOD_SCENE,
	            'u_ReflectIntensity': Shader3D.PERIOD_SCENE,
	            'u_AmbientColor': Shader3D.PERIOD_SCENE,
	            'u_shadowMap1': Shader3D.PERIOD_SCENE,
	            'u_shadowMap2': Shader3D.PERIOD_SCENE,
	            'u_shadowMap3': Shader3D.PERIOD_SCENE,
	            'u_shadowPSSMDistance': Shader3D.PERIOD_SCENE,
	            'u_lightShadowVP': Shader3D.PERIOD_SCENE,
	            'u_shadowPCFoffset': Shader3D.PERIOD_SCENE,
	            'u_FogStart': Shader3D.PERIOD_SCENE,
	            'u_FogRange': Shader3D.PERIOD_SCENE,
	            'u_FogColor': Shader3D.PERIOD_SCENE,
	            'u_DirationLightCount': Shader3D.PERIOD_SCENE,
	            'u_LightBuffer': Shader3D.PERIOD_SCENE,
	            'u_LightClusterBuffer': Shader3D.PERIOD_SCENE,
	            'u_DirectionLight.direction': Shader3D.PERIOD_SCENE,
	            'u_DirectionLight.color': Shader3D.PERIOD_SCENE,
	            'u_PointLight.position': Shader3D.PERIOD_SCENE,
	            'u_PointLight.range': Shader3D.PERIOD_SCENE,
	            'u_PointLight.color': Shader3D.PERIOD_SCENE,
	            'u_SpotLight.position': Shader3D.PERIOD_SCENE,
	            'u_SpotLight.direction': Shader3D.PERIOD_SCENE,
	            'u_SpotLight.range': Shader3D.PERIOD_SCENE,
	            'u_SpotLight.spot': Shader3D.PERIOD_SCENE,
	            'u_SpotLight.color': Shader3D.PERIOD_SCENE,
	        };
	        stateMap = {
	            's_Cull': Shader3D.RENDER_STATE_CULL,
	            's_Blend': Shader3D.RENDER_STATE_BLEND,
	            's_BlendSrc': Shader3D.RENDER_STATE_BLEND_SRC,
	            's_BlendDst': Shader3D.RENDER_STATE_BLEND_DST,
	            's_DepthTest': Shader3D.RENDER_STATE_DEPTH_TEST,
	            's_DepthWrite': Shader3D.RENDER_STATE_DEPTH_WRITE
	        };
	        shader = Shader3D.add("PBRStandard", null, null, true);
	        subShader = new SubShader(attributeMap, uniformMap);
	        shader.addSubShader(subShader);
	        subShader.addShaderPass(PBRStandardVS, PBRStandardPS, stateMap);
	        attributeMap = {
	            'a_Position': VertexMesh.MESH_POSITION0,
	            'a_Normal': VertexMesh.MESH_NORMAL0,
	            'a_Tangent0': VertexMesh.MESH_TANGENT0,
	            'a_Texcoord0': VertexMesh.MESH_TEXTURECOORDINATE0,
	            'a_BoneWeights': VertexMesh.MESH_BLENDWEIGHT0,
	            'a_BoneIndices': VertexMesh.MESH_BLENDINDICES0,
	            'a_MvpMatrix': VertexMesh.MESH_MVPMATRIX_ROW0,
	            'a_WorldMat': VertexMesh.MESH_WORLDMATRIX_ROW0
	        };
	        uniformMap = {
	            'u_Bones': Shader3D.PERIOD_CUSTOM,
	            'u_MvpMatrix': Shader3D.PERIOD_SPRITE,
	            'u_WorldMat': Shader3D.PERIOD_SPRITE,
	            'u_CameraPos': Shader3D.PERIOD_CAMERA,
	            'u_View': Shader3D.PERIOD_CAMERA,
	            'u_ProjectionParams': Shader3D.PERIOD_CAMERA,
	            'u_Viewport': Shader3D.PERIOD_CAMERA,
	            'u_AlphaTestValue': Shader3D.PERIOD_MATERIAL,
	            'u_AlbedoColor': Shader3D.PERIOD_MATERIAL,
	            'u_SpecularColor': Shader3D.PERIOD_MATERIAL,
	            'u_EmissionColor': Shader3D.PERIOD_MATERIAL,
	            'u_AlbedoTexture': Shader3D.PERIOD_MATERIAL,
	            'u_NormalTexture': Shader3D.PERIOD_MATERIAL,
	            'u_ParallaxTexture': Shader3D.PERIOD_MATERIAL,
	            'u_SpecularTexture': Shader3D.PERIOD_MATERIAL,
	            'u_OcclusionTexture': Shader3D.PERIOD_MATERIAL,
	            'u_EmissionTexture': Shader3D.PERIOD_MATERIAL,
	            'u_smoothness': Shader3D.PERIOD_MATERIAL,
	            'u_smoothnessScale': Shader3D.PERIOD_MATERIAL,
	            'u_occlusionStrength': Shader3D.PERIOD_MATERIAL,
	            'u_normalScale': Shader3D.PERIOD_MATERIAL,
	            'u_parallaxScale': Shader3D.PERIOD_MATERIAL,
	            'u_TilingOffset': Shader3D.PERIOD_MATERIAL,
	            'u_ReflectTexture': Shader3D.PERIOD_SCENE,
	            'u_ReflectIntensity': Shader3D.PERIOD_SCENE,
	            'u_AmbientColor': Shader3D.PERIOD_SCENE,
	            'u_shadowMap1': Shader3D.PERIOD_SCENE,
	            'u_shadowMap2': Shader3D.PERIOD_SCENE,
	            'u_shadowMap3': Shader3D.PERIOD_SCENE,
	            'u_shadowPSSMDistance': Shader3D.PERIOD_SCENE,
	            'u_lightShadowVP': Shader3D.PERIOD_SCENE,
	            'u_shadowPCFoffset': Shader3D.PERIOD_SCENE,
	            'u_FogStart': Shader3D.PERIOD_SCENE,
	            'u_FogRange': Shader3D.PERIOD_SCENE,
	            'u_FogColor': Shader3D.PERIOD_SCENE,
	            'u_DirationLightCount': Shader3D.PERIOD_SCENE,
	            'u_LightBuffer': Shader3D.PERIOD_SCENE,
	            'u_LightClusterBuffer': Shader3D.PERIOD_SCENE,
	            'u_DirectionLight.direction': Shader3D.PERIOD_SCENE,
	            'u_DirectionLight.color': Shader3D.PERIOD_SCENE,
	            'u_PointLight.position': Shader3D.PERIOD_SCENE,
	            'u_PointLight.range': Shader3D.PERIOD_SCENE,
	            'u_PointLight.color': Shader3D.PERIOD_SCENE,
	            'u_SpotLight.position': Shader3D.PERIOD_SCENE,
	            'u_SpotLight.direction': Shader3D.PERIOD_SCENE,
	            'u_SpotLight.range': Shader3D.PERIOD_SCENE,
	            'u_SpotLight.spot': Shader3D.PERIOD_SCENE,
	            'u_SpotLight.color': Shader3D.PERIOD_SCENE,
	        };
	        stateMap = {
	            's_Cull': Shader3D.RENDER_STATE_CULL,
	            's_Blend': Shader3D.RENDER_STATE_BLEND,
	            's_BlendSrc': Shader3D.RENDER_STATE_BLEND_SRC,
	            's_BlendDst': Shader3D.RENDER_STATE_BLEND_DST,
	            's_DepthTest': Shader3D.RENDER_STATE_DEPTH_TEST,
	            's_DepthWrite': Shader3D.RENDER_STATE_DEPTH_WRITE
	        };
	        shader = Shader3D.add("PBRSpecular", null, null, true);
	        subShader = new SubShader(attributeMap, uniformMap);
	        shader.addSubShader(subShader);
	        subShader.addShaderPass(PBRSpecularVS, PBRSpecularPS, stateMap);
	        attributeMap = {
	            'a_Position': VertexMesh.MESH_POSITION0,
	            'a_Color': VertexMesh.MESH_COLOR0,
	            'a_Texcoord0': VertexMesh.MESH_TEXTURECOORDINATE0,
	            'a_BoneWeights': VertexMesh.MESH_BLENDWEIGHT0,
	            'a_BoneIndices': VertexMesh.MESH_BLENDINDICES0,
	            'a_MvpMatrix': VertexMesh.MESH_MVPMATRIX_ROW0
	        };
	        uniformMap = {
	            'u_Bones': Shader3D.PERIOD_CUSTOM,
	            'u_AlbedoTexture': Shader3D.PERIOD_MATERIAL,
	            'u_AlbedoColor': Shader3D.PERIOD_MATERIAL,
	            'u_TilingOffset': Shader3D.PERIOD_MATERIAL,
	            'u_AlphaTestValue': Shader3D.PERIOD_MATERIAL,
	            'u_MvpMatrix': Shader3D.PERIOD_SPRITE,
	            'u_FogStart': Shader3D.PERIOD_SCENE,
	            'u_FogRange': Shader3D.PERIOD_SCENE,
	            'u_FogColor': Shader3D.PERIOD_SCENE
	        };
	        stateMap = {
	            's_Cull': Shader3D.RENDER_STATE_CULL,
	            's_Blend': Shader3D.RENDER_STATE_BLEND,
	            's_BlendSrc': Shader3D.RENDER_STATE_BLEND_SRC,
	            's_BlendDst': Shader3D.RENDER_STATE_BLEND_DST,
	            's_DepthTest': Shader3D.RENDER_STATE_DEPTH_TEST,
	            's_DepthWrite': Shader3D.RENDER_STATE_DEPTH_WRITE
	        };
	        shader = Shader3D.add("Unlit", null, null, true);
	        subShader = new SubShader(attributeMap, uniformMap);
	        shader.addSubShader(subShader);
	        subShader.addShaderPass(UnlitVS, UnlitPS, stateMap);
	        attributeMap = {
	            'a_Position': VertexMesh.MESH_POSITION0,
	            'a_Texcoord0': VertexMesh.MESH_TEXTURECOORDINATE0,
	            'a_BoneWeights': VertexMesh.MESH_BLENDWEIGHT0,
	            'a_BoneIndices': VertexMesh.MESH_BLENDINDICES0,
	            'a_MvpMatrix': VertexMesh.MESH_MVPMATRIX_ROW0
	        };
	        uniformMap = {
	            'u_Bones': Shader3D.PERIOD_CUSTOM,
	            'u_AlbedoTexture': Shader3D.PERIOD_MATERIAL,
	            'u_AlbedoColor': Shader3D.PERIOD_MATERIAL,
	            'u_TilingOffset': Shader3D.PERIOD_MATERIAL,
	            'u_AlphaTestValue': Shader3D.PERIOD_MATERIAL,
	            'u_MvpMatrix': Shader3D.PERIOD_SPRITE,
	            'u_FogStart': Shader3D.PERIOD_SCENE,
	            'u_FogRange': Shader3D.PERIOD_SCENE,
	            'u_FogColor': Shader3D.PERIOD_SCENE
	        };
	        stateMap = {
	            's_Cull': Shader3D.RENDER_STATE_CULL,
	            's_Blend': Shader3D.RENDER_STATE_BLEND,
	            's_BlendSrc': Shader3D.RENDER_STATE_BLEND_SRC,
	            's_BlendDst': Shader3D.RENDER_STATE_BLEND_DST,
	            's_DepthTest': Shader3D.RENDER_STATE_DEPTH_TEST,
	            's_DepthWrite': Shader3D.RENDER_STATE_DEPTH_WRITE
	        };
	        shader = Shader3D.add("Effect", null, null, true);
	        subShader = new SubShader(attributeMap, uniformMap);
	        shader.addSubShader(subShader);
	        subShader.addShaderPass(EffectVS, EffectPS, stateMap);
	        attributeMap = {
	            'a_CornerTextureCoordinate': VertexShuriKenParticle.PARTICLE_CORNERTEXTURECOORDINATE0,
	            'a_MeshPosition': VertexShuriKenParticle.PARTICLE_POSITION0,
	            'a_MeshColor': VertexShuriKenParticle.PARTICLE_COLOR0,
	            'a_MeshTextureCoordinate': VertexShuriKenParticle.PARTICLE_TEXTURECOORDINATE0,
	            'a_ShapePositionStartLifeTime': VertexShuriKenParticle.PARTICLE_SHAPEPOSITIONSTARTLIFETIME,
	            'a_DirectionTime': VertexShuriKenParticle.PARTICLE_DIRECTIONTIME,
	            'a_StartColor': VertexShuriKenParticle.PARTICLE_STARTCOLOR0,
	            'a_EndColor': VertexShuriKenParticle.PARTICLE_ENDCOLOR0,
	            'a_StartSize': VertexShuriKenParticle.PARTICLE_STARTSIZE,
	            'a_StartRotation0': VertexShuriKenParticle.PARTICLE_STARTROTATION,
	            'a_StartSpeed': VertexShuriKenParticle.PARTICLE_STARTSPEED,
	            'a_Random0': VertexShuriKenParticle.PARTICLE_RANDOM0,
	            'a_Random1': VertexShuriKenParticle.PARTICLE_RANDOM1,
	            'a_SimulationWorldPostion': VertexShuriKenParticle.PARTICLE_SIMULATIONWORLDPOSTION,
	            'a_SimulationWorldRotation': VertexShuriKenParticle.PARTICLE_SIMULATIONWORLDROTATION
	        };
	        uniformMap = {
	            'u_Tintcolor': Shader3D.PERIOD_MATERIAL,
	            'u_TilingOffset': Shader3D.PERIOD_MATERIAL,
	            'u_texture': Shader3D.PERIOD_MATERIAL,
	            'u_WorldPosition': Shader3D.PERIOD_SPRITE,
	            'u_WorldRotation': Shader3D.PERIOD_SPRITE,
	            'u_PositionScale': Shader3D.PERIOD_SPRITE,
	            'u_SizeScale': Shader3D.PERIOD_SPRITE,
	            'u_ScalingMode': Shader3D.PERIOD_SPRITE,
	            'u_Gravity': Shader3D.PERIOD_SPRITE,
	            'u_ThreeDStartRotation': Shader3D.PERIOD_SPRITE,
	            'u_StretchedBillboardLengthScale': Shader3D.PERIOD_SPRITE,
	            'u_StretchedBillboardSpeedScale': Shader3D.PERIOD_SPRITE,
	            'u_SimulationSpace': Shader3D.PERIOD_SPRITE,
	            'u_CurrentTime': Shader3D.PERIOD_SPRITE,
	            'u_ColorOverLifeGradientAlphas': Shader3D.PERIOD_SPRITE,
	            'u_ColorOverLifeGradientColors': Shader3D.PERIOD_SPRITE,
	            'u_MaxColorOverLifeGradientAlphas': Shader3D.PERIOD_SPRITE,
	            'u_MaxColorOverLifeGradientColors': Shader3D.PERIOD_SPRITE,
	            'u_VOLVelocityConst': Shader3D.PERIOD_SPRITE,
	            'u_VOLVelocityGradientX': Shader3D.PERIOD_SPRITE,
	            'u_VOLVelocityGradientY': Shader3D.PERIOD_SPRITE,
	            'u_VOLVelocityGradientZ': Shader3D.PERIOD_SPRITE,
	            'u_VOLVelocityConstMax': Shader3D.PERIOD_SPRITE,
	            'u_VOLVelocityGradientMaxX': Shader3D.PERIOD_SPRITE,
	            'u_VOLVelocityGradientMaxY': Shader3D.PERIOD_SPRITE,
	            'u_VOLVelocityGradientMaxZ': Shader3D.PERIOD_SPRITE,
	            'u_VOLSpaceType': Shader3D.PERIOD_SPRITE,
	            'u_SOLSizeGradient': Shader3D.PERIOD_SPRITE,
	            'u_SOLSizeGradientX': Shader3D.PERIOD_SPRITE,
	            'u_SOLSizeGradientY': Shader3D.PERIOD_SPRITE,
	            'u_SOLSizeGradientZ': Shader3D.PERIOD_SPRITE,
	            'u_SOLSizeGradientMax': Shader3D.PERIOD_SPRITE,
	            'u_SOLSizeGradientMaxX': Shader3D.PERIOD_SPRITE,
	            'u_SOLSizeGradientMaxY': Shader3D.PERIOD_SPRITE,
	            'u_SOLSizeGradientMaxZ': Shader3D.PERIOD_SPRITE,
	            'u_ROLAngularVelocityConst': Shader3D.PERIOD_SPRITE,
	            'u_ROLAngularVelocityConstSeprarate': Shader3D.PERIOD_SPRITE,
	            'u_ROLAngularVelocityGradient': Shader3D.PERIOD_SPRITE,
	            'u_ROLAngularVelocityGradientX': Shader3D.PERIOD_SPRITE,
	            'u_ROLAngularVelocityGradientY': Shader3D.PERIOD_SPRITE,
	            'u_ROLAngularVelocityGradientZ': Shader3D.PERIOD_SPRITE,
	            'u_ROLAngularVelocityConstMax': Shader3D.PERIOD_SPRITE,
	            'u_ROLAngularVelocityConstMaxSeprarate': Shader3D.PERIOD_SPRITE,
	            'u_ROLAngularVelocityGradientMax': Shader3D.PERIOD_SPRITE,
	            'u_ROLAngularVelocityGradientMaxX': Shader3D.PERIOD_SPRITE,
	            'u_ROLAngularVelocityGradientMaxY': Shader3D.PERIOD_SPRITE,
	            'u_ROLAngularVelocityGradientMaxZ': Shader3D.PERIOD_SPRITE,
	            'u_ROLAngularVelocityGradientMaxW': Shader3D.PERIOD_SPRITE,
	            'u_TSACycles': Shader3D.PERIOD_SPRITE,
	            'u_TSASubUVLength': Shader3D.PERIOD_SPRITE,
	            'u_TSAGradientUVs': Shader3D.PERIOD_SPRITE,
	            'u_TSAMaxGradientUVs': Shader3D.PERIOD_SPRITE,
	            'u_CameraPos': Shader3D.PERIOD_CAMERA,
	            'u_CameraDirection': Shader3D.PERIOD_CAMERA,
	            'u_CameraUp': Shader3D.PERIOD_CAMERA,
	            'u_View': Shader3D.PERIOD_CAMERA,
	            'u_Projection': Shader3D.PERIOD_CAMERA,
	            'u_FogStart': Shader3D.PERIOD_SCENE,
	            'u_FogRange': Shader3D.PERIOD_SCENE,
	            'u_FogColor': Shader3D.PERIOD_SCENE
	        };
	        stateMap = {
	            's_Cull': Shader3D.RENDER_STATE_CULL,
	            's_Blend': Shader3D.RENDER_STATE_BLEND,
	            's_BlendSrc': Shader3D.RENDER_STATE_BLEND_SRC,
	            's_BlendDst': Shader3D.RENDER_STATE_BLEND_DST,
	            's_DepthTest': Shader3D.RENDER_STATE_DEPTH_TEST,
	            's_DepthWrite': Shader3D.RENDER_STATE_DEPTH_WRITE
	        };
	        shader = Shader3D.add("PARTICLESHURIKEN");
	        subShader = new SubShader(attributeMap, uniformMap);
	        shader.addSubShader(subShader);
	        subShader.addShaderPass(ParticleShuriKenVS, ParticleShuriKenPS, stateMap);
	        attributeMap = {
	            'a_Position': VertexMesh.MESH_POSITION0
	        };
	        uniformMap = {
	            'u_TintColor': Shader3D.PERIOD_MATERIAL,
	            'u_Exposure': Shader3D.PERIOD_MATERIAL,
	            'u_Rotation': Shader3D.PERIOD_MATERIAL,
	            'u_CubeTexture': Shader3D.PERIOD_MATERIAL,
	            'u_ViewProjection': Shader3D.PERIOD_CAMERA
	        };
	        shader = Shader3D.add("SkyBox");
	        subShader = new SubShader(attributeMap, uniformMap);
	        shader.addSubShader(subShader);
	        subShader.addShaderPass(SkyBoxVS, SkyBoxPS);
	        attributeMap = {
	            'a_Position': VertexMesh.MESH_POSITION0
	        };
	        uniformMap = {
	            'u_SunSize': Shader3D.PERIOD_MATERIAL,
	            'u_SunSizeConvergence': Shader3D.PERIOD_MATERIAL,
	            'u_AtmosphereThickness': Shader3D.PERIOD_MATERIAL,
	            'u_SkyTint': Shader3D.PERIOD_MATERIAL,
	            'u_GroundTint': Shader3D.PERIOD_MATERIAL,
	            'u_Exposure': Shader3D.PERIOD_MATERIAL,
	            'u_ViewProjection': Shader3D.PERIOD_CAMERA,
	            'u_SunLight.direction': Shader3D.PERIOD_SCENE,
	            'u_SunLight.color': Shader3D.PERIOD_SCENE,
	        };
	        shader = Shader3D.add("SkyBoxProcedural");
	        subShader = new SubShader(attributeMap, uniformMap);
	        shader.addSubShader(subShader);
	        subShader.addShaderPass(SkyBoxProceduralVS, SkyBoxProceduralPS);
	        attributeMap = {
	            'a_Position': VertexMesh.MESH_POSITION0,
	            'a_Normal': VertexMesh.MESH_NORMAL0,
	            'a_Texcoord0': VertexMesh.MESH_TEXTURECOORDINATE0
	        };
	        uniformMap = {
	            'u_MvpMatrix': Shader3D.PERIOD_SPRITE,
	            'u_WorldMat': Shader3D.PERIOD_SPRITE,
	            'u_CameraPos': Shader3D.PERIOD_CAMERA,
	            'u_LightmapScaleOffset': Shader3D.PERIOD_SPRITE,
	            'u_LightMap': Shader3D.PERIOD_SPRITE,
	            'u_SplatAlphaTexture': Shader3D.PERIOD_MATERIAL,
	            'u_DiffuseTexture1': Shader3D.PERIOD_MATERIAL,
	            'u_DiffuseTexture2': Shader3D.PERIOD_MATERIAL,
	            'u_DiffuseTexture3': Shader3D.PERIOD_MATERIAL,
	            'u_DiffuseTexture4': Shader3D.PERIOD_MATERIAL,
	            'u_DiffuseTexture5': Shader3D.PERIOD_MATERIAL,
	            'u_DiffuseScaleOffset1': Shader3D.PERIOD_MATERIAL,
	            'u_DiffuseScaleOffset2': Shader3D.PERIOD_MATERIAL,
	            'u_DiffuseScaleOffset3': Shader3D.PERIOD_MATERIAL,
	            'u_DiffuseScaleOffset4': Shader3D.PERIOD_MATERIAL,
	            'u_DiffuseScaleOffset5': Shader3D.PERIOD_MATERIAL,
	            'u_FogStart': Shader3D.PERIOD_SCENE,
	            'u_FogRange': Shader3D.PERIOD_SCENE,
	            'u_FogColor': Shader3D.PERIOD_SCENE,
	            'u_DirectionLight.Direction': Shader3D.PERIOD_SCENE,
	            'u_DirectionLight.Color': Shader3D.PERIOD_SCENE,
	            'u_PointLight.Position': Shader3D.PERIOD_SCENE,
	            'u_PointLight.Range': Shader3D.PERIOD_SCENE,
	            'u_PointLight.Attenuation': Shader3D.PERIOD_SCENE,
	            'u_PointLight.Color': Shader3D.PERIOD_SCENE,
	            'u_SpotLight.Position': Shader3D.PERIOD_SCENE,
	            'u_SpotLight.Direction': Shader3D.PERIOD_SCENE,
	            'u_SpotLight.Range': Shader3D.PERIOD_SCENE,
	            'u_SpotLight.Spot': Shader3D.PERIOD_SCENE,
	            'u_SpotLight.Color': Shader3D.PERIOD_SCENE,
	            'u_AmbientColor': Shader3D.PERIOD_SCENE,
	            'u_shadowMap1': Shader3D.PERIOD_SCENE,
	            'u_shadowMap2': Shader3D.PERIOD_SCENE,
	            'u_shadowMap3': Shader3D.PERIOD_SCENE,
	            'u_shadowPSSMDistance': Shader3D.PERIOD_SCENE,
	            'u_lightShadowVP': Shader3D.PERIOD_SCENE,
	            'u_shadowPCFoffset': Shader3D.PERIOD_SCENE
	        };
	        stateMap = {
	            's_Cull': Shader3D.RENDER_STATE_CULL,
	            's_Blend': Shader3D.RENDER_STATE_BLEND,
	            's_BlendSrc': Shader3D.RENDER_STATE_BLEND_SRC,
	            's_BlendDst': Shader3D.RENDER_STATE_BLEND_DST,
	            's_DepthTest': Shader3D.RENDER_STATE_DEPTH_TEST,
	            's_DepthWrite': Shader3D.RENDER_STATE_DEPTH_WRITE
	        };
	        shader = Shader3D.add("ExtendTerrain");
	        subShader = new SubShader(attributeMap, uniformMap);
	        shader.addSubShader(subShader);
	        subShader.addShaderPass(extendTerrainVS, extendTerrainPS, stateMap);
	        attributeMap = {
	            'a_Position': VertexTrail.TRAIL_POSITION0,
	            'a_OffsetVector': VertexTrail.TRAIL_OFFSETVECTOR,
	            'a_Texcoord0X': VertexTrail.TRAIL_TEXTURECOORDINATE0X,
	            'a_Texcoord0Y': VertexTrail.TRAIL_TEXTURECOORDINATE0Y,
	            'a_BirthTime': VertexTrail.TRAIL_TIME0,
	            'a_Color': VertexTrail.TRAIL_COLOR
	        };
	        uniformMap = {
	            'u_MvpMatrix': Shader3D.PERIOD_SPRITE,
	            'u_View': Shader3D.PERIOD_CAMERA,
	            'u_Projection': Shader3D.PERIOD_CAMERA,
	            'u_TilingOffset': Shader3D.PERIOD_MATERIAL,
	            'u_MainTexture': Shader3D.PERIOD_MATERIAL,
	            'u_MainColor': Shader3D.PERIOD_MATERIAL,
	            'u_CurTime': Shader3D.PERIOD_SPRITE,
	            'u_LifeTime': Shader3D.PERIOD_SPRITE,
	            'u_WidthCurve': Shader3D.PERIOD_SPRITE,
	            'u_WidthCurveKeyLength': Shader3D.PERIOD_SPRITE,
	            'u_GradientColorkey': Shader3D.PERIOD_SPRITE,
	            'u_GradientAlphakey': Shader3D.PERIOD_SPRITE
	        };
	        stateMap = {
	            's_Cull': Shader3D.RENDER_STATE_CULL,
	            's_Blend': Shader3D.RENDER_STATE_BLEND,
	            's_BlendSrc': Shader3D.RENDER_STATE_BLEND_SRC,
	            's_BlendDst': Shader3D.RENDER_STATE_BLEND_DST,
	            's_DepthTest': Shader3D.RENDER_STATE_DEPTH_TEST,
	            's_DepthWrite': Shader3D.RENDER_STATE_DEPTH_WRITE
	        };
	        shader = Shader3D.add("Trail");
	        subShader = new SubShader(attributeMap, uniformMap);
	        shader.addSubShader(subShader);
	        subShader.addShaderPass(TrailVS, TrailPS, stateMap);
	        attributeMap = {
	            'a_Position': VertexMesh.MESH_POSITION0,
	            'a_Normal': VertexMesh.MESH_NORMAL0,
	            'a_Tangent0': VertexMesh.MESH_TANGENT0
	        };
	        uniformMap = {
	            'u_MvpMatrix': Shader3D.PERIOD_SPRITE,
	            'u_WorldMat': Shader3D.PERIOD_SPRITE,
	            'u_CameraPos': Shader3D.PERIOD_CAMERA,
	            'u_Time': Shader3D.PERIOD_SCENE,
	            'u_MainTexture': Shader3D.PERIOD_MATERIAL,
	            'u_NormalTexture': Shader3D.PERIOD_MATERIAL,
	            'u_HorizonColor': Shader3D.PERIOD_MATERIAL,
	            'u_WaveScale': Shader3D.PERIOD_MATERIAL,
	            'u_WaveSpeed': Shader3D.PERIOD_MATERIAL
	        };
	        shader = Shader3D.add("WaterPrimary");
	        subShader = new SubShader(attributeMap, uniformMap);
	        shader.addSubShader(subShader);
	        subShader.addShaderPass(WaterPrimaryVS, WaterPrimaryPS);
	        attributeMap = {
	            'a_PositionTexcoord': VertexMesh.MESH_POSITION0
	        };
	        uniformMap = {
	            'u_MainTex': Shader3D.PERIOD_MATERIAL
	        };
	        shader = Shader3D.add("BlitScreen");
	        subShader = new SubShader(attributeMap, uniformMap);
	        shader.addSubShader(subShader);
	        var shaderPass = subShader.addShaderPass(BlitScreenVS, BlitScreenPS);
	        var renderState = shaderPass.renderState;
	        renderState.depthTest = RenderState.DEPTHTEST_ALWAYS;
	        renderState.depthWrite = false;
	        renderState.cull = RenderState.CULL_NONE;
	        renderState.blend = RenderState.BLEND_DISABLE;
	        attributeMap = {
	            'a_PositionTexcoord': VertexMesh.MESH_POSITION0
	        };
	        uniformMap = {
	            'u_MainTex': Shader3D.PERIOD_MATERIAL,
	            'u_BloomTex': Shader3D.PERIOD_MATERIAL,
	            'u_AutoExposureTex': Shader3D.PERIOD_MATERIAL,
	            'u_MainTex_TexelSize': Shader3D.PERIOD_MATERIAL,
	            'u_SampleScale': Shader3D.PERIOD_MATERIAL,
	            'u_Threshold': Shader3D.PERIOD_MATERIAL,
	            'u_Params': Shader3D.PERIOD_MATERIAL
	        };
	        shader = Shader3D.add("PostProcessBloom");
	        subShader = new SubShader(attributeMap, uniformMap);
	        shader.addSubShader(subShader);
	        shaderPass = subShader.addShaderPass(BloomVS, BloomPrefilter13PS);
	        renderState = shaderPass.renderState;
	        renderState.depthTest = RenderState.DEPTHTEST_ALWAYS;
	        renderState.depthWrite = false;
	        renderState.cull = RenderState.CULL_NONE;
	        renderState.blend = RenderState.BLEND_DISABLE;
	        subShader = new SubShader(attributeMap, uniformMap);
	        shader.addSubShader(subShader);
	        shaderPass = subShader.addShaderPass(BloomVS, BloomPrefilter4PS);
	        renderState = shaderPass.renderState;
	        renderState.depthTest = RenderState.DEPTHTEST_ALWAYS;
	        renderState.depthWrite = false;
	        renderState.cull = RenderState.CULL_NONE;
	        renderState.blend = RenderState.BLEND_DISABLE;
	        subShader = new SubShader(attributeMap, uniformMap);
	        shader.addSubShader(subShader);
	        shaderPass = subShader.addShaderPass(BloomVS, BloomDownsample13PS);
	        renderState = shaderPass.renderState;
	        renderState.depthTest = RenderState.DEPTHTEST_ALWAYS;
	        renderState.depthWrite = false;
	        renderState.cull = RenderState.CULL_NONE;
	        renderState.blend = RenderState.BLEND_DISABLE;
	        subShader = new SubShader(attributeMap, uniformMap);
	        shader.addSubShader(subShader);
	        shaderPass = subShader.addShaderPass(BloomVS, BloomDownsample4PS);
	        renderState = shaderPass.renderState;
	        renderState.depthTest = RenderState.DEPTHTEST_ALWAYS;
	        renderState.depthWrite = false;
	        renderState.cull = RenderState.CULL_NONE;
	        renderState.blend = RenderState.BLEND_DISABLE;
	        subShader = new SubShader(attributeMap, uniformMap);
	        shader.addSubShader(subShader);
	        shaderPass = subShader.addShaderPass(BloomVS, BloomUpsampleTentPS);
	        renderState = shaderPass.renderState;
	        renderState.depthTest = RenderState.DEPTHTEST_ALWAYS;
	        renderState.depthWrite = false;
	        renderState.cull = RenderState.CULL_NONE;
	        renderState.blend = RenderState.BLEND_DISABLE;
	        subShader = new SubShader(attributeMap, uniformMap);
	        shader.addSubShader(subShader);
	        shaderPass = subShader.addShaderPass(BloomVS, BloomUpsampleBoxPS);
	        renderState = shaderPass.renderState;
	        renderState.depthTest = RenderState.DEPTHTEST_ALWAYS;
	        renderState.depthWrite = false;
	        renderState.cull = RenderState.CULL_NONE;
	        renderState.blend = RenderState.BLEND_DISABLE;
	        attributeMap = {
	            'a_PositionTexcoord': VertexMesh.MESH_POSITION0
	        };
	        uniformMap = {
	            'u_MainTex': Shader3D.PERIOD_MATERIAL,
	            'u_BloomTex': Shader3D.PERIOD_MATERIAL,
	            'u_AutoExposureTex': Shader3D.PERIOD_MATERIAL,
	            'u_Bloom_DirtTileOffset': Shader3D.PERIOD_MATERIAL,
	            'u_Bloom_DirtTex': Shader3D.PERIOD_MATERIAL,
	            'u_BloomTex_TexelSize': Shader3D.PERIOD_MATERIAL,
	            'u_Bloom_Settings': Shader3D.PERIOD_MATERIAL,
	            'u_Bloom_Color': Shader3D.PERIOD_MATERIAL
	        };
	        shader = Shader3D.add("PostProcessComposite");
	        subShader = new SubShader(attributeMap, uniformMap);
	        shader.addSubShader(subShader);
	        shaderPass = subShader.addShaderPass(CompositeVS, CompositePS);
	        renderState = shaderPass.renderState;
	        renderState.depthTest = RenderState.DEPTHTEST_ALWAYS;
	        renderState.depthWrite = false;
	        renderState.cull = RenderState.CULL_NONE;
	        renderState.blend = RenderState.BLEND_DISABLE;
	    }
	}

	class ParallelSplitShadowMap {
	    constructor() {
	        this._spiltDistance = [];
	        this._currentPSSM = -1;
	        this._shadowMapCount = 3;
	        this._maxDistance = 200.0;
	        this._ratioOfDistance = 1.0 / this._shadowMapCount;
	        this._globalParallelLightDir = new Vector3(0, -1, 0);
	        this._statesDirty = true;
	        this._shadowMapTextureSize = 1024;
	        this._scene = null;
	        this._boundingSphere = new Array(ParallelSplitShadowMap.MAX_PSSM_COUNT + 1);
	        this._boundingBox = new Array(ParallelSplitShadowMap.MAX_PSSM_COUNT + 1);
	        this._frustumPos = new Array((ParallelSplitShadowMap.MAX_PSSM_COUNT + 1) * 4);
	        this._uniformDistance = new Array(ParallelSplitShadowMap.MAX_PSSM_COUNT + 1);
	        this._logDistance = new Array(ParallelSplitShadowMap.MAX_PSSM_COUNT + 1);
	        this._dimension = new Array(ParallelSplitShadowMap.MAX_PSSM_COUNT + 1);
	        this._PCFType = 0;
	        this._tempLookAt3 = new Vector3();
	        this._tempLookAt4 = new Vector4();
	        this._tempValue = new Vector4();
	        this._tempPos = new Vector3();
	        this._tempLightUp = new Vector3();
	        this._tempMin = new Vector4();
	        this._tempMax = new Vector4();
	        this._tempMatrix44 = new Matrix4x4;
	        this._splitFrustumCulling = new BoundFrustum(Matrix4x4.DEFAULT);
	        this._tempScaleMatrix44 = new Matrix4x4();
	        this._shadowPCFOffset = new Vector2(1.0 / 1024.0, 1.0 / 1024.0);
	        this._shaderValueDistance = new Vector4();
	        this._shaderValueLightVP = null;
	        this.cameras = [];
	        this._shaderValueVPs = [];
	        var i;
	        for (i = 0; i < this._spiltDistance.length; i++) {
	            this._spiltDistance[i] = 0.0;
	        }
	        for (i = 0; i < this._dimension.length; i++) {
	            this._dimension[i] = new Vector2();
	        }
	        for (i = 0; i < this._frustumPos.length; i++) {
	            this._frustumPos[i] = new Vector3();
	        }
	        for (i = 0; i < this._boundingBox.length; i++) {
	            this._boundingBox[i] = new BoundBox(new Vector3(), new Vector3());
	        }
	        for (i = 0; i < this._boundingSphere.length; i++) {
	            this._boundingSphere[i] = new BoundSphere(new Vector3(), 0.0);
	        }
	        Matrix4x4.createScaling(new Vector3(0.5, 0.5, 1.0), this._tempScaleMatrix44);
	        this._tempScaleMatrix44.elements[12] = 0.5;
	        this._tempScaleMatrix44.elements[13] = 0.5;
	    }
	    setInfo(scene, maxDistance, globalParallelDir, shadowMapTextureSize, numberOfPSSM, PCFType) {
	        if (numberOfPSSM > ParallelSplitShadowMap.MAX_PSSM_COUNT) {
	            this._shadowMapCount = ParallelSplitShadowMap.MAX_PSSM_COUNT;
	        }
	        this._scene = scene;
	        this._maxDistance = maxDistance;
	        this.shadowMapCount = numberOfPSSM;
	        this._globalParallelLightDir = globalParallelDir;
	        this._ratioOfDistance = 1.0 / this._shadowMapCount;
	        for (var i = 0; i < this._spiltDistance.length; i++) {
	            this._spiltDistance[i] = 0.0;
	        }
	        this._shadowMapTextureSize = shadowMapTextureSize;
	        this._shadowPCFOffset.x = 1.0 / this._shadowMapTextureSize;
	        this._shadowPCFOffset.y = 1.0 / this._shadowMapTextureSize;
	        this.setPCFType(PCFType);
	        this._statesDirty = true;
	    }
	    setPCFType(PCFtype) {
	        this._PCFType = PCFtype;
	        var defineData = this._scene._shaderValues;
	        switch (this._PCFType) {
	            case 0:
	                defineData.addDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_PCF_NO);
	                defineData.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_PCF1);
	                defineData.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_PCF2);
	                defineData.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_PCF3);
	                break;
	            case 1:
	                defineData.addDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_PCF1);
	                defineData.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_PCF_NO);
	                defineData.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_PCF2);
	                defineData.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_PCF3);
	                break;
	            case 2:
	                defineData.addDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_PCF2);
	                defineData.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_PCF_NO);
	                defineData.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_PCF1);
	                defineData.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_PCF3);
	                break;
	            case 3:
	                defineData.addDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_PCF3);
	                defineData.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_PCF_NO);
	                defineData.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_PCF1);
	                defineData.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_PCF2);
	                break;
	        }
	    }
	    getPCFType() {
	        return this._PCFType;
	    }
	    setFarDistance(value) {
	        if (this._maxDistance != value) {
	            this._maxDistance = value;
	            this._statesDirty = true;
	        }
	    }
	    getFarDistance() {
	        return this._maxDistance;
	    }
	    set shadowMapCount(value) {
	        value = value > 0 ? value : 1;
	        value = value <= ParallelSplitShadowMap.MAX_PSSM_COUNT ? value : ParallelSplitShadowMap.MAX_PSSM_COUNT;
	        if (this._shadowMapCount != value) {
	            this._shadowMapCount = value;
	            this._ratioOfDistance = 1.0 / this._shadowMapCount;
	            this._statesDirty = true;
	            this._shaderValueLightVP = new Float32Array(value * 16);
	            this._shaderValueVPs.length = value;
	            for (var i = 0; i < value; i++)
	                this._shaderValueVPs[i] = new Float32Array(this._shaderValueLightVP.buffer, i * 64);
	        }
	    }
	    get shadowMapCount() {
	        return this._shadowMapCount;
	    }
	    _beginSampler(index, sceneCamera) {
	        if (index < 0 || index > this._shadowMapCount)
	            throw new Error("ParallelSplitShadowMap: beginSample invalid index");
	        this._currentPSSM = index;
	        this._update(sceneCamera);
	    }
	    endSampler(sceneCamera) {
	        this._currentPSSM = -1;
	    }
	    _calcAllLightCameraInfo(sceneCamera) {
	        if (this._shadowMapCount === 1) {
	            this._beginSampler(0, sceneCamera);
	            this.endSampler(sceneCamera);
	        }
	        else {
	            for (var i = 0, n = this._shadowMapCount + 1; i < n; i++) {
	                this._beginSampler(i, sceneCamera);
	                this.endSampler(sceneCamera);
	            }
	        }
	    }
	    _recalculate(nearPlane, fieldOfView, aspectRatio) {
	        this._calcSplitDistance(nearPlane);
	        this._calcBoundingBox(fieldOfView, aspectRatio);
	        this._rebuildRenderInfo();
	    }
	    _update(sceneCamera) {
	        var nearPlane = sceneCamera.nearPlane;
	        var fieldOfView = sceneCamera.fieldOfView;
	        var aspectRatio = sceneCamera.aspectRatio;
	        if (this._statesDirty || this.lastNearPlane !== nearPlane || this.lastFieldOfView !== fieldOfView || this.lastAspectRatio !== aspectRatio) {
	            this._recalculate(nearPlane, fieldOfView, aspectRatio);
	            this._uploadShaderValue();
	            this._statesDirty = false;
	            this.lastNearPlane = nearPlane;
	            this.lastFieldOfView = fieldOfView;
	            this.lastAspectRatio = aspectRatio;
	        }
	        this._calcLightViewProject(sceneCamera);
	    }
	    _uploadShaderValue() {
	        var sceneSV = this._scene._shaderValues;
	        switch (this._shadowMapCount) {
	            case 1:
	                sceneSV.addDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_PSSM1);
	                sceneSV.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_PSSM2);
	                sceneSV.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_PSSM3);
	                break;
	            case 2:
	                sceneSV.addDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_PSSM2);
	                sceneSV.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_PSSM1);
	                sceneSV.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_PSSM3);
	                break;
	            case 3:
	                sceneSV.addDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_PSSM3);
	                sceneSV.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_PSSM1);
	                sceneSV.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_PSSM2);
	                break;
	        }
	        sceneSV.setVector(ILaya3D.Scene3D.SHADOWDISTANCE, this._shaderValueDistance);
	        sceneSV.setBuffer(ILaya3D.Scene3D.SHADOWLIGHTVIEWPROJECT, this._shaderValueLightVP);
	        sceneSV.setVector2(ILaya3D.Scene3D.SHADOWMAPPCFOFFSET, this._shadowPCFOffset);
	        switch (this._shadowMapCount) {
	            case 3:
	                sceneSV.setTexture(ILaya3D.Scene3D.SHADOWMAPTEXTURE1, this.cameras[1].renderTarget);
	                sceneSV.setTexture(ILaya3D.Scene3D.SHADOWMAPTEXTURE2, this.cameras[2].renderTarget);
	                sceneSV.setTexture(ILaya3D.Scene3D.SHADOWMAPTEXTURE3, this.cameras[3].renderTarget);
	                break;
	            case 2:
	                sceneSV.setTexture(ILaya3D.Scene3D.SHADOWMAPTEXTURE1, this.cameras[1].renderTarget);
	                sceneSV.setTexture(ILaya3D.Scene3D.SHADOWMAPTEXTURE2, this.cameras[2].renderTarget);
	                break;
	            case 1:
	                sceneSV.setTexture(ILaya3D.Scene3D.SHADOWMAPTEXTURE1, this.cameras[1].renderTarget);
	                break;
	        }
	    }
	    _calcSplitDistance(nearPlane) {
	        var far = this._maxDistance;
	        var invNumberOfPSSM = 1.0 / this._shadowMapCount;
	        var i;
	        for (i = 0; i <= this._shadowMapCount; i++) {
	            this._uniformDistance[i] = nearPlane + (far - nearPlane) * i * invNumberOfPSSM;
	        }
	        var farDivNear = far / nearPlane;
	        for (i = 0; i <= this._shadowMapCount; i++) {
	            var n = Math.pow(farDivNear, i * invNumberOfPSSM);
	            this._logDistance[i] = nearPlane * n;
	        }
	        for (i = 0; i <= this._shadowMapCount; i++) {
	            this._spiltDistance[i] = this._uniformDistance[i] * this._ratioOfDistance + this._logDistance[i] * (1.0 - this._ratioOfDistance);
	        }
	        this._shaderValueDistance.x = (this._spiltDistance[1] != undefined) && (this._spiltDistance[1]);
	        this._shaderValueDistance.y = (this._spiltDistance[2] != undefined) && (this._spiltDistance[2]);
	        this._shaderValueDistance.z = (this._spiltDistance[3] != undefined) && (this._spiltDistance[3]);
	        this._shaderValueDistance.w = (this._spiltDistance[4] != undefined) && (this._spiltDistance[4]);
	    }
	    _calcBoundingBox(fieldOfView, aspectRatio) {
	        var fov = 3.1415926 * fieldOfView / 180.0;
	        var halfTanValue = Math.tan(fov / 2.0);
	        var height;
	        var width;
	        var distance;
	        var i;
	        for (i = 0; i <= this._shadowMapCount; i++) {
	            distance = this._spiltDistance[i];
	            height = distance * halfTanValue;
	            width = height * aspectRatio;
	            var temp = this._frustumPos[i * 4 + 0];
	            temp.x = -width;
	            temp.y = -height;
	            temp.z = -distance;
	            temp = this._frustumPos[i * 4 + 1];
	            temp.x = width;
	            temp.y = -height;
	            temp.z = -distance;
	            temp = this._frustumPos[i * 4 + 2];
	            temp.x = -width;
	            temp.y = height;
	            temp.z = -distance;
	            temp = this._frustumPos[i * 4 + 3];
	            temp.x = width;
	            temp.y = height;
	            temp.z = -distance;
	            temp = this._dimension[i];
	            temp.x = width;
	            temp.y = height;
	        }
	        var d;
	        var min;
	        var max;
	        var center;
	        for (i = 1; i <= this._shadowMapCount; i++) {
	            d = this._dimension[i];
	            min = this._boundingBox[i].min;
	            min.x = -d.x;
	            min.y = -d.y;
	            min.z = -this._spiltDistance[i];
	            max = this._boundingBox[i].max;
	            max.x = d.x;
	            max.y = d.y;
	            max.z = -this._spiltDistance[i - 1];
	            center = this._boundingSphere[i].center;
	            center.x = (min.x + max.x) * 0.5;
	            center.y = (min.y + max.y) * 0.5;
	            center.z = (min.z + max.z) * 0.5;
	            this._boundingSphere[i].radius = Math.sqrt(Math.pow(max.x - min.x, 2) + Math.pow(max.y - min.y, 2) + Math.pow(max.z - min.z, 2)) * 0.5;
	        }
	        min = this._boundingBox[0].min;
	        d = this._dimension[this._shadowMapCount];
	        min.x = -d.x;
	        min.y = -d.y;
	        min.z = -this._spiltDistance[this._shadowMapCount];
	        max = this._boundingBox[0].max;
	        max.x = d.x;
	        max.y = d.y;
	        max.z = -this._spiltDistance[0];
	        center = this._boundingSphere[0].center;
	        center.x = (min.x + max.x) * 0.5;
	        center.y = (min.y + max.y) * 0.5;
	        center.z = (min.z + max.z) * 0.5;
	        this._boundingSphere[0].radius = Math.sqrt(Math.pow(max.x - min.x, 2) + Math.pow(max.y - min.y, 2) + Math.pow(max.z - min.z, 2)) * 0.5;
	    }
	    calcSplitFrustum(sceneCamera) {
	        if (this._currentPSSM > 0) {
	            Matrix4x4.createPerspective(3.1416 * sceneCamera.fieldOfView / 180.0, sceneCamera.aspectRatio, this._spiltDistance[this._currentPSSM - 1], this._spiltDistance[this._currentPSSM], this._tempMatrix44);
	        }
	        else {
	            Matrix4x4.createPerspective(3.1416 * sceneCamera.fieldOfView / 180.0, sceneCamera.aspectRatio, this._spiltDistance[0], this._spiltDistance[this._shadowMapCount], this._tempMatrix44);
	        }
	        Matrix4x4.multiply(this._tempMatrix44, sceneCamera.viewMatrix, this._tempMatrix44);
	        this._splitFrustumCulling.matrix = this._tempMatrix44;
	    }
	    _rebuildRenderInfo() {
	        var nNum = this._shadowMapCount + 1;
	        var i;
	        this.cameras.length = nNum;
	        for (i = 0; i < nNum; i++) {
	            if (!this.cameras[i]) {
	                var camera = new Camera();
	                camera.name = "lightCamera" + i;
	                camera.clearColor = new Vector4(1.0, 1.0, 1.0, 1.0);
	                this.cameras[i] = camera;
	            }
	            var shadowMap = this.cameras[i].renderTarget;
	            if (shadowMap == null || shadowMap.width != this._shadowMapTextureSize || shadowMap.height != this._shadowMapTextureSize) {
	                (shadowMap) && (shadowMap.destroy());
	                shadowMap = new RenderTexture(this._shadowMapTextureSize, this._shadowMapTextureSize, Laya.RenderTextureFormat.R8G8B8A8, Laya.RenderTextureDepthFormat.DEPTH_16);
	                shadowMap.filterMode = Laya.BaseTexture.FILTERMODE_POINT;
	                this.cameras[i].renderTarget = shadowMap;
	            }
	        }
	    }
	    _calcLightViewProject(sceneCamera) {
	        var boundSphere = this._boundingSphere[this._currentPSSM];
	        var cameraMatViewInv = sceneCamera.transform.worldMatrix;
	        var radius = boundSphere.radius;
	        boundSphere.center.cloneTo(this._tempLookAt3);
	        Vector3.transformV3ToV4(this._tempLookAt3, cameraMatViewInv, this._tempLookAt4);
	        var lookAt3Element = this._tempLookAt3;
	        var lookAt4Element = this._tempLookAt4;
	        lookAt3Element.x = lookAt4Element.x;
	        lookAt3Element.y = lookAt4Element.y;
	        lookAt3Element.z = lookAt4Element.z;
	        var lightUpElement = this._tempLightUp;
	        sceneCamera.transform.worldMatrix.getForward(ParallelSplitShadowMap._tempVector30);
	        var sceneCameraDir = ParallelSplitShadowMap._tempVector30;
	        lightUpElement.x = sceneCameraDir.x;
	        lightUpElement.y = 1.0;
	        lightUpElement.z = sceneCameraDir.z;
	        Vector3.normalize(this._tempLightUp, this._tempLightUp);
	        Vector3.scale(this._globalParallelLightDir, boundSphere.radius * 4, this._tempPos);
	        Vector3.subtract(this._tempLookAt3, this._tempPos, this._tempPos);
	        var curLightCamera = this.cameras[this._currentPSSM];
	        curLightCamera.transform.position = this._tempPos;
	        curLightCamera.transform.lookAt(this._tempLookAt3, this._tempLightUp, false);
	        var tempMax = this._tempMax;
	        var tempMin = this._tempMin;
	        tempMax.x = tempMax.y = tempMax.z = -100000.0;
	        tempMax.w = 1.0;
	        tempMin.x = tempMin.y = tempMin.z = 100000.0;
	        tempMin.w = 1.0;
	        Matrix4x4.multiply(curLightCamera.viewMatrix, cameraMatViewInv, this._tempMatrix44);
	        var tempValueElement = this._tempValue;
	        var corners = [];
	        corners.length = 8;
	        this._boundingBox[this._currentPSSM].getCorners(corners);
	        for (var i = 0; i < 8; i++) {
	            var frustumPosElements = corners[i];
	            tempValueElement.x = frustumPosElements.x;
	            tempValueElement.y = frustumPosElements.y;
	            tempValueElement.z = frustumPosElements.z;
	            tempValueElement.w = 1.0;
	            Vector4.transformByM4x4(this._tempValue, this._tempMatrix44, this._tempValue);
	            tempMin.x = (tempValueElement.x < tempMin.x) ? tempValueElement.x : tempMin.x;
	            tempMin.y = (tempValueElement.y < tempMin.y) ? tempValueElement.y : tempMin.y;
	            tempMin.z = (tempValueElement.z < tempMin.z) ? tempValueElement.z : tempMin.z;
	            tempMax.x = (tempValueElement.x > tempMax.x) ? tempValueElement.x : tempMax.x;
	            tempMax.y = (tempValueElement.y > tempMax.y) ? tempValueElement.y : tempMax.y;
	            tempMax.z = (tempValueElement.z > tempMax.z) ? tempValueElement.z : tempMax.z;
	        }
	        Vector4.add(this._tempMax, this._tempMin, this._tempValue);
	        tempValueElement.x *= 0.5;
	        tempValueElement.y *= 0.5;
	        tempValueElement.z *= 0.5;
	        tempValueElement.w = 1;
	        Vector4.transformByM4x4(this._tempValue, curLightCamera.transform.worldMatrix, this._tempValue);
	        var distance = Math.abs(-this._tempMax.z);
	        var farPlane = distance > this._maxDistance ? distance : this._maxDistance;
	        Vector3.scale(this._globalParallelLightDir, farPlane, this._tempPos);
	        var tempPosElement = this._tempPos;
	        tempPosElement.x = tempValueElement.x - tempPosElement.x;
	        tempPosElement.y = tempValueElement.y - tempPosElement.y;
	        tempPosElement.z = tempValueElement.z - tempPosElement.z;
	        curLightCamera.transform.position = this._tempPos;
	        curLightCamera.transform.lookAt(this._tempLookAt3, this._tempLightUp, false);
	        Matrix4x4.createOrthoOffCenter(tempMin.x, tempMax.x, tempMin.y, tempMax.y, 1.0, farPlane + 0.5 * (tempMax.z - tempMin.z), curLightCamera.projectionMatrix);
	        var projectView = curLightCamera.projectionViewMatrix;
	        ParallelSplitShadowMap.multiplyMatrixOutFloat32Array(this._tempScaleMatrix44, projectView, this._shaderValueVPs[this._currentPSSM]);
	        this._scene._shaderValues.setBuffer(ILaya3D.Scene3D.SHADOWLIGHTVIEWPROJECT, this._shaderValueLightVP);
	    }
	    static multiplyMatrixOutFloat32Array(left, right, out) {
	        var i, a, b, ai0, ai1, ai2, ai3;
	        a = left.elements;
	        b = right.elements;
	        for (i = 0; i < 4; i++) {
	            ai0 = a[i];
	            ai1 = a[i + 4];
	            ai2 = a[i + 8];
	            ai3 = a[i + 12];
	            out[i] = ai0 * b[0] + ai1 * b[1] + ai2 * b[2] + ai3 * b[3];
	            out[i + 4] = ai0 * b[4] + ai1 * b[5] + ai2 * b[6] + ai3 * b[7];
	            out[i + 8] = ai0 * b[8] + ai1 * b[9] + ai2 * b[10] + ai3 * b[11];
	            out[i + 12] = ai0 * b[12] + ai1 * b[13] + ai2 * b[14] + ai3 * b[15];
	        }
	    }
	    setShadowMapTextureSize(size) {
	        if (size !== this._shadowMapTextureSize) {
	            this._shadowMapTextureSize = size;
	            this._shadowPCFOffset.x = 1 / this._shadowMapTextureSize;
	            this._shadowPCFOffset.y = 1 / this._shadowMapTextureSize;
	            this._statesDirty = true;
	        }
	    }
	    disposeAllRenderTarget() {
	        for (var i = 0, n = this._shadowMapCount + 1; i < n; i++) {
	            if (this.cameras[i].renderTarget) {
	                this.cameras[i].renderTarget.destroy();
	                this.cameras[i].renderTarget = null;
	            }
	        }
	    }
	}
	ParallelSplitShadowMap.MAX_PSSM_COUNT = 3;
	ParallelSplitShadowMap._tempVector30 = new Vector3();

	class LightSprite extends Sprite3D {
	    constructor() {
	        super();
	        this._isAlternate = false;
	        this._intensity = 1.0;
	        this._intensityColor = new Vector3();
	        this.color = new Vector3(1.0, 1.0, 1.0);
	        this._shadow = false;
	        this._shadowFarPlane = 8;
	        this._shadowMapSize = 512;
	        this._shadowMapCount = 1;
	        this._shadowMapPCFType = 0;
	        this._lightmapBakedType = LightSprite.LIGHTMAPBAKEDTYPE_REALTIME;
	    }
	    get intensity() {
	        return this._intensity;
	    }
	    set intensity(value) {
	        this._intensity = value;
	    }
	    get shadow() {
	        return this._shadow;
	    }
	    set shadow(value) {
	        throw new Error("LightSprite: must override it.");
	    }
	    get shadowDistance() {
	        return this._shadowFarPlane;
	    }
	    set shadowDistance(value) {
	        this._shadowFarPlane = value;
	        (this._parallelSplitShadowMap) && (this._parallelSplitShadowMap.setFarDistance(value));
	    }
	    get shadowResolution() {
	        return this._shadowMapSize;
	    }
	    set shadowResolution(value) {
	        this._shadowMapSize = value;
	        (this._parallelSplitShadowMap) && (this._parallelSplitShadowMap.setShadowMapTextureSize(value));
	    }
	    get shadowPSSMCount() {
	        return this._shadowMapCount;
	    }
	    set shadowPSSMCount(value) {
	        this._shadowMapCount = value;
	        (this._parallelSplitShadowMap) && (this._parallelSplitShadowMap.shadowMapCount = value);
	    }
	    get shadowPCFType() {
	        return this._shadowMapPCFType;
	    }
	    set shadowPCFType(value) {
	        this._shadowMapPCFType = value;
	        (this._parallelSplitShadowMap) && (this._parallelSplitShadowMap.setPCFType(value));
	    }
	    get lightmapBakedType() {
	        return this._lightmapBakedType;
	    }
	    set lightmapBakedType(value) {
	        if (this._lightmapBakedType !== value) {
	            this._lightmapBakedType = value;
	            if (this.activeInHierarchy) {
	                if (value !== LightSprite.LIGHTMAPBAKEDTYPE_BAKED)
	                    this._addToScene();
	                else
	                    this._removeFromScene();
	            }
	        }
	    }
	    _parse(data, spriteMap) {
	        super._parse(data, spriteMap);
	        var colorData = data.color;
	        this.color.fromArray(colorData);
	        this.intensity = data.intensity;
	        this.lightmapBakedType = data.lightmapBakedType;
	    }
	    _addToScene() {
	        var scene = this._scene;
	        var maxLightCount = Config3D._config.maxLightCount;
	        if (scene._lightCount < maxLightCount) {
	            scene._lightCount++;
	            this._addToLightQueue();
	            this._isAlternate = false;
	        }
	        else {
	            scene._alternateLights.add(this);
	            this._isAlternate = true;
	            console.warn("LightSprite:light count has large than maxLightCount,the latest added light will be ignore.");
	        }
	    }
	    _removeFromScene() {
	        var scene = this._scene;
	        if (this._isAlternate) {
	            scene._alternateLights.remove(this);
	        }
	        else {
	            scene._lightCount--;
	            this._removeFromLightQueue();
	            if (scene._alternateLights._length > 0) {
	                var alternateLight = scene._alternateLights.shift();
	                alternateLight._addToLightQueue();
	                alternateLight._isAlternate = false;
	                scene._lightCount++;
	            }
	        }
	    }
	    _addToLightQueue() {
	    }
	    _removeFromLightQueue() {
	    }
	    _onActive() {
	        super._onActive();
	        (this.lightmapBakedType !== LightSprite.LIGHTMAPBAKEDTYPE_BAKED) && (this._addToScene());
	    }
	    _onInActive() {
	        super._onInActive();
	        (this.lightmapBakedType !== LightSprite.LIGHTMAPBAKEDTYPE_BAKED) && (this._removeFromScene());
	    }
	    _create() {
	        return new LightSprite();
	    }
	    get diffuseColor() {
	        console.log("LightSprite: discard property,please use color property instead.");
	        return this.color;
	    }
	    set diffuseColor(value) {
	        console.log("LightSprite: discard property,please use color property instead.");
	        this.color = value;
	    }
	}
	LightSprite.LIGHTMAPBAKEDTYPE_REALTIME = 0;
	LightSprite.LIGHTMAPBAKEDTYPE_MIXED = 1;
	LightSprite.LIGHTMAPBAKEDTYPE_BAKED = 2;

	class DirectionLight extends LightSprite {
	    set shadow(value) {
	        if (this._shadow !== value) {
	            this._shadow = value;
	            (this.scene) && (this._initShadow());
	        }
	    }
	    constructor() {
	        super();
	        this._direction = new Vector3();
	    }
	    _initShadow() {
	        if (this._shadow) {
	            this._parallelSplitShadowMap = new ParallelSplitShadowMap();
	            this.scene.parallelSplitShadowMaps.push(this._parallelSplitShadowMap);
	            this.transform.worldMatrix.getForward(this._direction);
	            Vector3.normalize(this._direction, this._direction);
	            this._parallelSplitShadowMap.setInfo(this.scene, this._shadowFarPlane, this._direction, this._shadowMapSize, this._shadowMapCount, this._shadowMapPCFType);
	        }
	        else {
	            var defineDatas = this._scene._shaderValues;
	            var parallelSplitShadowMaps = this.scene.parallelSplitShadowMaps;
	            parallelSplitShadowMaps.splice(parallelSplitShadowMaps.indexOf(this._parallelSplitShadowMap), 1);
	            this._parallelSplitShadowMap.disposeAllRenderTarget();
	            this._parallelSplitShadowMap = null;
	            defineDatas.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_PSSM1);
	            defineDatas.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_PSSM2);
	            defineDatas.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_PSSM3);
	        }
	    }
	    _addToLightQueue() {
	        this._scene._directionLights.add(this);
	    }
	    _removeFromLightQueue() {
	        this._scene._directionLights.remove(this);
	    }
	}

	class PointLight extends LightSprite {
	    get range() {
	        return this._range;
	    }
	    set range(value) {
	        this._range = value;
	    }
	    constructor() {
	        super();
	        this._range = 6.0;
	    }
	    _addToLightQueue() {
	        this._scene._pointLights.add(this);
	    }
	    _removeFromLightQueue() {
	        this._scene._pointLights.remove(this);
	    }
	    _parse(data, spriteMap) {
	        super._parse(data, spriteMap);
	        this.range = data.range;
	    }
	}

	class SpotLight extends LightSprite {
	    get spotAngle() {
	        return this._spotAngle;
	    }
	    set spotAngle(value) {
	        this._spotAngle = Math.max(Math.min(value, 179), 0);
	    }
	    get range() {
	        return this._range;
	    }
	    set range(value) {
	        this._range = value;
	    }
	    constructor() {
	        super();
	        this._spotAngle = 30.0;
	        this._range = 10.0;
	        this._direction = new Vector3();
	    }
	    _addToLightQueue() {
	        this._scene._spotLights.add(this);
	    }
	    _removeFromLightQueue() {
	        this._scene._spotLights.remove(this);
	    }
	    _parse(data, spriteMap) {
	        super._parse(data, spriteMap);
	        this.range = data.range;
	        this.spotAngle = data.spotAngle;
	    }
	}

	class Scene3DUtils {
	    static _createSprite3DInstance(nodeData, spriteMap, outBatchSprites) {
	        var node;
	        switch (nodeData.type) {
	            case "Scene3D":
	                node = new Scene3D();
	                break;
	            case "Sprite3D":
	                node = new Sprite3D();
	                break;
	            case "MeshSprite3D":
	                node = new MeshSprite3D();
	                (outBatchSprites && nodeData.props.isStatic) && (outBatchSprites.push(node));
	                break;
	            case "SkinnedMeshSprite3D":
	                node = new SkinnedMeshSprite3D();
	                break;
	            case "ShuriKenParticle3D":
	                node = new ShuriKenParticle3D();
	                break;
	            case "Camera":
	                node = new Camera();
	                break;
	            case "DirectionLight":
	                node = new DirectionLight();
	                break;
	            case "PointLight":
	                node = new PointLight();
	                break;
	            case "SpotLight":
	                node = new SpotLight();
	                break;
	            case "TrailSprite3D":
	                node = new TrailSprite3D();
	                break;
	            default:
	                throw new Error("Utils3D:unidentified class type in (.lh) file.");
	        }
	        var childData = nodeData.child;
	        if (childData) {
	            for (var i = 0, n = childData.length; i < n; i++) {
	                var child = Scene3DUtils._createSprite3DInstance(childData[i], spriteMap, outBatchSprites);
	                node.addChild(child);
	            }
	        }
	        spriteMap[nodeData.instanceID] = node;
	        return node;
	    }
	    static _createComponentInstance(nodeData, spriteMap) {
	        var node = spriteMap[nodeData.instanceID];
	        node._parse(nodeData.props, spriteMap);
	        var childData = nodeData.child;
	        if (childData) {
	            for (var i = 0, n = childData.length; i < n; i++)
	                Scene3DUtils._createComponentInstance(childData[i], spriteMap);
	        }
	        var componentsData = nodeData.components;
	        if (componentsData) {
	            for (var j = 0, m = componentsData.length; j < m; j++) {
	                var data = componentsData[j];
	                var clas = Laya.ClassUtils.getRegClass(data.type);
	                if (clas) {
	                    var component = node.addComponent(clas);
	                    component._parse(data);
	                }
	                else {
	                    console.warn("Unkown component type.");
	                }
	            }
	        }
	    }
	    static _createNodeByJson02(nodeData, outBatchSprites) {
	        var spriteMap = {};
	        var node = Scene3DUtils._createSprite3DInstance(nodeData, spriteMap, outBatchSprites);
	        Scene3DUtils._createComponentInstance(nodeData, spriteMap);
	        return node;
	    }
	    static _parse(data, propertyParams = null, constructParams = null) {
	        var json = data.data;
	        var outBatchSprits = [];
	        var sprite;
	        switch (data.version) {
	            case "LAYAHIERARCHY:02":
	                sprite = Scene3DUtils._createNodeByJson02(json, outBatchSprits);
	                break;
	            default:
	                sprite = Scene3DUtils._createNodeByJson(json, outBatchSprits);
	        }
	        StaticBatchManager.combine(sprite, outBatchSprits);
	        return sprite;
	    }
	    static _parseScene(data, propertyParams = null, constructParams = null) {
	        var json = data.data;
	        var outBatchSprits = [];
	        var scene;
	        switch (data.version) {
	            case "LAYASCENE3D:02":
	                scene = Scene3DUtils._createNodeByJson02(json, outBatchSprits);
	                break;
	            default:
	                scene = Scene3DUtils._createNodeByJson(json, outBatchSprits);
	        }
	        StaticBatchManager.combine(null, outBatchSprits);
	        return scene;
	    }
	    static _createNodeByJson(nodeData, outBatchSprites) {
	        var node;
	        switch (nodeData.type) {
	            case "Scene3D":
	                node = new Scene3D();
	                break;
	            case "Sprite3D":
	                node = new Sprite3D();
	                break;
	            case "MeshSprite3D":
	                node = new MeshSprite3D();
	                (outBatchSprites && nodeData.props.isStatic) && (outBatchSprites.push(node));
	                break;
	            case "SkinnedMeshSprite3D":
	                node = new SkinnedMeshSprite3D();
	                break;
	            case "ShuriKenParticle3D":
	                node = new ShuriKenParticle3D();
	                break;
	            case "Camera":
	                node = new Camera();
	                break;
	            case "DirectionLight":
	                node = new DirectionLight();
	                break;
	            case "PointLight":
	                node = new PointLight();
	                break;
	            case "SpotLight":
	                node = new SpotLight();
	                break;
	            case "TrailSprite3D":
	                node = new TrailSprite3D();
	                break;
	            default:
	                throw new Error("Utils3D:unidentified class type in (.lh) file.");
	        }
	        var childData = nodeData.child;
	        if (childData) {
	            for (var i = 0, n = childData.length; i < n; i++) {
	                var child = Scene3DUtils._createNodeByJson(childData[i], outBatchSprites);
	                node.addChild(child);
	            }
	        }
	        var componentsData = nodeData.components;
	        if (componentsData) {
	            for (var j = 0, m = componentsData.length; j < m; j++) {
	                var data = componentsData[j];
	                var clas = Laya.ClassUtils.getRegClass(data.type);
	                if (clas) {
	                    var component = node.addComponent(clas);
	                    component._parse(data);
	                }
	                else {
	                    console.warn("Unkown component type.");
	                }
	            }
	        }
	        node._parse(nodeData.props, null);
	        return node;
	    }
	}

	class Laya3D {
	    constructor() {
	    }
	    static get enbalePhysics() {
	        return Physics3D._enbalePhysics;
	    }
	    static _cancelLoadByUrl(url) {
	        Laya.Laya.loader.cancelLoadByUrl(url);
	        Laya3D._innerFirstLevelLoaderManager.cancelLoadByUrl(url);
	        Laya3D._innerSecondLevelLoaderManager.cancelLoadByUrl(url);
	        Laya3D._innerThirdLevelLoaderManager.cancelLoadByUrl(url);
	        Laya3D._innerFourthLevelLoaderManager.cancelLoadByUrl(url);
	    }
	    static _changeWebGLSize(width, height) {
	        Laya.WebGL.onStageResize(width, height);
	        RenderContext3D.clientWidth = width;
	        RenderContext3D.clientHeight = height;
	    }
	    static __init__(width, height, config) {
	        Laya.Config.isAntialias = config.isAntialias;
	        Laya.Config.isAlpha = config.isAlpha;
	        Laya.Config.premultipliedAlpha = config.premultipliedAlpha;
	        Laya.Config.isStencil = config.isStencil;
	        if (!Laya.WebGL.enable()) {
	            alert("Laya3D init error,must support webGL!");
	            return;
	        }
	        Laya.RunDriver.changeWebGLSize = Laya3D._changeWebGLSize;
	        Laya.Render.is3DMode = true;
	        Laya.Laya.init(width, height);
	        if (!Laya.Render.supportWebGLPlusRendering) {
	            Laya.LayaGL.instance = Laya.WebGLContext.mainContext;
	            Laya.LayaGL.instance.createCommandEncoder = function (reserveSize = 128, adjustSize = 64, isSyncToRenderThread = false) {
	                return new Laya.CommandEncoder(this, reserveSize, adjustSize, isSyncToRenderThread);
	            };
	        }
	        config._multiLighting = config.enbaleMultiLight && SystemUtils.supportTextureFormat(Laya.TextureFormat.R32G32B32A32);
	        ILaya3D.Scene3D = Scene3D;
	        ILaya3D.MeshRenderStaticBatchManager = MeshRenderStaticBatchManager;
	        ILaya3D.MeshRenderDynamicBatchManager = MeshRenderDynamicBatchManager;
	        ILaya3D.SubMeshDynamicBatch = SubMeshDynamicBatch;
	        ILaya3D.Laya3D = Laya3D;
	        ILaya3D.Matrix4x4 = Matrix4x4;
	        Laya3D.enableNative3D();
	        VertexElementFormat.__init__();
	        VertexMesh.__init__();
	        VertexShurikenParticleBillboard.__init__();
	        VertexShurikenParticleMesh.__init__();
	        VertexPositionTexture0.__init__();
	        VertexTrail.__init__();
	        VertexPositionTerrain.__init__();
	        PixelLineVertex.__init__();
	        SubMeshInstanceBatch.__init__();
	        SubMeshDynamicBatch.__init__();
	        Physics3D._physics3D = window.Physics3D;
	        if (Physics3D._physics3D) {
	            StaticPlaneColliderShape.__init__();
	            ColliderShape.__init__();
	            CompoundColliderShape.__init__();
	            PhysicsComponent.__init__();
	            PhysicsSimulation.__init__();
	            BoxColliderShape.__init__();
	            CylinderColliderShape.__init__();
	            CharacterController.__init__();
	            Rigidbody3D.__init__();
	        }
	        ShaderInit3D.__init__();
	        Mesh.__init__();
	        PrimitiveMesh.__init__();
	        Sprite3D.__init__();
	        RenderableSprite3D.__init__();
	        MeshSprite3D.__init__();
	        SkinnedMeshSprite3D.__init__();
	        ShuriKenParticle3D.__init__();
	        TrailSprite3D.__init__();
	        PostProcess.__init__();
	        Scene3D.__init__();
	        MeshRenderStaticBatchManager.__init__();
	        BaseMaterial.__initDefine__();
	        BlinnPhongMaterial.__initDefine__();
	        PBRStandardMaterial.__initDefine__();
	        PBRSpecularMaterial.__initDefine__();
	        SkyProceduralMaterial.__initDefine__();
	        UnlitMaterial.__initDefine__();
	        TrailMaterial.__initDefine__();
	        EffectMaterial.__initDefine__();
	        WaterPrimaryMaterial.__initDefine__();
	        ShurikenParticleMaterial.__initDefine__();
	        ExtendTerrainMaterial.__initDefine__();
	        PixelLineMaterial.__initDefine__();
	        SkyBoxMaterial.__initDefine__();
	        Command.__init__();
	        Laya.ClassUtils.regClass("Laya.EffectMaterial", EffectMaterial);
	        Laya.ClassUtils.regClass("Laya.UnlitMaterial", UnlitMaterial);
	        Laya.ClassUtils.regClass("Laya.BlinnPhongMaterial", BlinnPhongMaterial);
	        Laya.ClassUtils.regClass("Laya.SkyProceduralMaterial", SkyProceduralMaterial);
	        Laya.ClassUtils.regClass("Laya.PBRStandardMaterial", PBRStandardMaterial);
	        Laya.ClassUtils.regClass("Laya.PBRSpecularMaterial", PBRSpecularMaterial);
	        Laya.ClassUtils.regClass("Laya.SkyBoxMaterial", SkyBoxMaterial);
	        Laya.ClassUtils.regClass("Laya.WaterPrimaryMaterial", WaterPrimaryMaterial);
	        Laya.ClassUtils.regClass("Laya.ExtendTerrainMaterial", ExtendTerrainMaterial);
	        Laya.ClassUtils.regClass("Laya.ShurikenParticleMaterial", ShurikenParticleMaterial);
	        Laya.ClassUtils.regClass("Laya.TrailMaterial", TrailMaterial);
	        Laya.ClassUtils.regClass("Laya.PhysicsCollider", PhysicsCollider);
	        Laya.ClassUtils.regClass("Laya.Rigidbody3D", Rigidbody3D);
	        Laya.ClassUtils.regClass("Laya.CharacterController", CharacterController);
	        Laya.ClassUtils.regClass("Laya.Animator", Animator);
	        Laya.ClassUtils.regClass("PhysicsCollider", PhysicsCollider);
	        Laya.ClassUtils.regClass("CharacterController", CharacterController);
	        Laya.ClassUtils.regClass("Animator", Animator);
	        Laya.ClassUtils.regClass("Rigidbody3D", Rigidbody3D);
	        PixelLineMaterial.defaultMaterial = new PixelLineMaterial();
	        BlinnPhongMaterial.defaultMaterial = new BlinnPhongMaterial();
	        EffectMaterial.defaultMaterial = new EffectMaterial();
	        PBRStandardMaterial.defaultMaterial = new PBRStandardMaterial();
	        PBRSpecularMaterial.defaultMaterial = new PBRSpecularMaterial();
	        UnlitMaterial.defaultMaterial = new UnlitMaterial();
	        ShurikenParticleMaterial.defaultMaterial = new ShurikenParticleMaterial();
	        TrailMaterial.defaultMaterial = new TrailMaterial();
	        SkyProceduralMaterial.defaultMaterial = new SkyProceduralMaterial();
	        SkyBoxMaterial.defaultMaterial = new SkyBoxMaterial();
	        WaterPrimaryMaterial.defaultMaterial = new WaterPrimaryMaterial();
	        PixelLineMaterial.defaultMaterial.lock = true;
	        BlinnPhongMaterial.defaultMaterial.lock = true;
	        EffectMaterial.defaultMaterial.lock = true;
	        PBRStandardMaterial.defaultMaterial.lock = true;
	        PBRSpecularMaterial.defaultMaterial.lock = true;
	        UnlitMaterial.defaultMaterial.lock = true;
	        ShurikenParticleMaterial.defaultMaterial.lock = true;
	        TrailMaterial.defaultMaterial.lock = true;
	        SkyProceduralMaterial.defaultMaterial.lock = true;
	        SkyBoxMaterial.defaultMaterial.lock = true;
	        WaterPrimaryMaterial.defaultMaterial.lock = true;
	        Laya.Texture2D.__init__();
	        TextureCube.__init__();
	        SkyBox.__init__();
	        SkyDome.__init__();
	        ScreenQuad.__init__();
	        ScreenTriangle.__init__();
	        FrustumCulling.__init__();
	        HalfFloatUtils.__init__();
	        var createMap = Laya.LoaderManager.createMap;
	        createMap["lh"] = [Laya3D.HIERARCHY, Scene3DUtils._parse];
	        createMap["ls"] = [Laya3D.HIERARCHY, Scene3DUtils._parseScene];
	        createMap["lm"] = [Laya3D.MESH, Mesh._parse];
	        createMap["lmat"] = [Laya3D.MATERIAL, BaseMaterial._parse];
	        createMap["ltc"] = [Laya3D.TEXTURECUBE, TextureCube._parse];
	        createMap["jpg"] = [Laya3D.TEXTURE2D, Laya.Texture2D._parse];
	        createMap["jpeg"] = [Laya3D.TEXTURE2D, Laya.Texture2D._parse];
	        createMap["bmp"] = [Laya3D.TEXTURE2D, Laya.Texture2D._parse];
	        createMap["gif"] = [Laya3D.TEXTURE2D, Laya.Texture2D._parse];
	        createMap["png"] = [Laya3D.TEXTURE2D, Laya.Texture2D._parse];
	        createMap["dds"] = [Laya3D.TEXTURE2D, Laya.Texture2D._parse];
	        createMap["ktx"] = [Laya3D.TEXTURE2D, Laya.Texture2D._parse];
	        createMap["pvr"] = [Laya3D.TEXTURE2D, Laya.Texture2D._parse];
	        createMap["lani"] = [Laya3D.ANIMATIONCLIP, AnimationClip._parse];
	        createMap["lav"] = [Laya3D.AVATAR, Avatar._parse];
	        var parserMap = Laya.Loader.parserMap;
	        parserMap[Laya3D.HIERARCHY] = Laya3D._loadHierarchy;
	        parserMap[Laya3D.MESH] = Laya3D._loadMesh;
	        parserMap[Laya3D.MATERIAL] = Laya3D._loadMaterial;
	        parserMap[Laya3D.TEXTURECUBE] = Laya3D._loadTextureCube;
	        parserMap[Laya3D.TEXTURE2D] = Laya3D._loadTexture2D;
	        parserMap[Laya3D.ANIMATIONCLIP] = Laya3D._loadAnimationClip;
	        parserMap[Laya3D.AVATAR] = Laya3D._loadAvatar;
	        Laya3D._innerFirstLevelLoaderManager.on(Laya.Event.ERROR, null, Laya3D._eventLoadManagerError);
	        Laya3D._innerSecondLevelLoaderManager.on(Laya.Event.ERROR, null, Laya3D._eventLoadManagerError);
	        Laya3D._innerThirdLevelLoaderManager.on(Laya.Event.ERROR, null, Laya3D._eventLoadManagerError);
	        Laya3D._innerFourthLevelLoaderManager.on(Laya.Event.ERROR, null, Laya3D._eventLoadManagerError);
	    }
	    static enableNative3D() {
	        var shaderData = ShaderData;
	        var shader3D = ShaderInstance;
	        var skinnedMeshRender = SkinnedMeshRenderer;
	        var avatar = Avatar;
	        var frustumCulling = FrustumCulling;
	        if (Laya.Render.supportWebGLPlusRendering) {
	            shaderData.prototype._initData = shaderData.prototype._initDataForNative;
	            shaderData.prototype.setBool = shaderData.prototype.setBoolForNative;
	            shaderData.prototype.getBool = shaderData.prototype.getBoolForNative;
	            shaderData.prototype.setInt = shaderData.prototype.setIntForNative;
	            shaderData.prototype.getInt = shaderData.prototype.getIntForNative;
	            shaderData.prototype.setNumber = shaderData.prototype.setNumberForNative;
	            shaderData.prototype.getNumber = shaderData.prototype.getNumberForNative;
	            shaderData.prototype.setVector = shaderData.prototype.setVectorForNative;
	            shaderData.prototype.getVector = shaderData.prototype.getVectorForNative;
	            shaderData.prototype.setVector2 = shaderData.prototype.setVector2ForNative;
	            shaderData.prototype.getVector2 = shaderData.prototype.getVector2ForNative;
	            shaderData.prototype.setVector3 = shaderData.prototype.setVector3ForNative;
	            shaderData.prototype.getVector3 = shaderData.prototype.getVector3ForNative;
	            shaderData.prototype.setQuaternion = shaderData.prototype.setQuaternionForNative;
	            shaderData.prototype.getQuaternion = shaderData.prototype.getQuaternionForNative;
	            shaderData.prototype.setMatrix4x4 = shaderData.prototype.setMatrix4x4ForNative;
	            shaderData.prototype.getMatrix4x4 = shaderData.prototype.getMatrix4x4ForNative;
	            shaderData.prototype.setBuffer = shaderData.prototype.setBufferForNative;
	            shaderData.prototype.getBuffer = shaderData.prototype.getBufferForNative;
	            shaderData.prototype.setTexture = shaderData.prototype.setTextureForNative;
	            shaderData.prototype.getTexture = shaderData.prototype.getTextureForNative;
	            shaderData.prototype.setAttribute = shaderData.prototype.setAttributeForNative;
	            shaderData.prototype.getAttribute = shaderData.prototype.getAttributeForNative;
	            shaderData.prototype.cloneTo = shaderData.prototype.cloneToForNative;
	            shaderData.prototype.getData = shaderData.prototype.getDataForNative;
	            shader3D.prototype._uniformMatrix2fv = shader3D.prototype._uniformMatrix2fvForNative;
	            shader3D.prototype._uniformMatrix3fv = shader3D.prototype._uniformMatrix3fvForNative;
	            shader3D.prototype._uniformMatrix4fv = shader3D.prototype._uniformMatrix4fvForNative;
	            Laya.LayaGLRunner.uploadShaderUniforms = Laya.LayaGLRunner.uploadShaderUniformsForNative;
	        }
	        if (Laya.Render.supportWebGLPlusCulling) {
	            frustumCulling.renderObjectCulling = FrustumCulling.renderObjectCullingNative;
	        }
	        if (Laya.Render.supportWebGLPlusAnimation) {
	            avatar.prototype._cloneDatasToAnimator = avatar.prototype._cloneDatasToAnimatorNative;
	            var animationClip = AnimationClip;
	            animationClip.prototype._evaluateClipDatasRealTime = animationClip.prototype._evaluateClipDatasRealTimeForNative;
	            skinnedMeshRender.prototype._computeSkinnedData = skinnedMeshRender.prototype._computeSkinnedDataForNative;
	        }
	        if (Laya.Render.isConchApp) {
	            Laya.WebGL.shaderHighPrecision = false;
	            var gl = Laya.LayaGL.instance;
	            var precisionFormat = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT);
	            precisionFormat.precision ? Laya.WebGL.shaderHighPrecision = true : Laya.WebGL.shaderHighPrecision = false;
	        }
	    }
	    static formatRelativePath(base, value) {
	        var path;
	        path = base + value;
	        var char1 = value.charAt(0);
	        if (char1 === ".") {
	            var parts = path.split("/");
	            for (var i = 0, len = parts.length; i < len; i++) {
	                if (parts[i] == '..') {
	                    var index = i - 1;
	                    if (index > 0 && parts[index] !== '..') {
	                        parts.splice(index, 2);
	                        i -= 2;
	                    }
	                }
	            }
	            path = parts.join('/');
	        }
	        return path;
	    }
	    static _endLoad(loader, content = null, subResous = null) {
	        if (subResous) {
	            for (var i = 0, n = subResous.length; i < n; i++) {
	                var resou = Laya.Loader.getRes(subResous[i]);
	                (resou) && (resou._removeReference());
	            }
	        }
	        loader.endLoad(content);
	    }
	    static _eventLoadManagerError(msg) {
	        Laya.Laya.loader.event(Laya.Event.ERROR, msg);
	    }
	    static _addHierarchyInnerUrls(urls, urlMap, urlVersion, hierarchyBasePath, path, type, constructParams = null, propertyParams = null) {
	        var formatUrl = Laya3D.formatRelativePath(hierarchyBasePath, path);
	        (urlVersion) && (formatUrl = formatUrl + urlVersion);
	        urls.push({ url: formatUrl, type: type, constructParams: constructParams, propertyParams: propertyParams });
	        urlMap.push(formatUrl);
	        return formatUrl;
	    }
	    static _getSprite3DHierarchyInnerUrls(node, firstLevelUrls, secondLevelUrls, thirdLevelUrls, fourthLelUrls, subUrls, urlVersion, hierarchyBasePath) {
	        var i, n;
	        var props = node.props;
	        switch (node.type) {
	            case "Scene3D":
	                var lightmaps = props.lightmaps;
	                for (i = 0, n = lightmaps.length; i < n; i++) {
	                    var lightMap = lightmaps[i];
	                    lightMap.path = Laya3D._addHierarchyInnerUrls(fourthLelUrls, subUrls, urlVersion, hierarchyBasePath, lightMap.path, Laya3D.TEXTURE2D, lightMap.constructParams, lightMap.propertyParams);
	                }
	                var reflectionTextureData = props.reflectionTexture;
	                (reflectionTextureData) && (props.reflectionTexture = Laya3D._addHierarchyInnerUrls(thirdLevelUrls, subUrls, urlVersion, hierarchyBasePath, reflectionTextureData, Laya3D.TEXTURECUBE));
	                if (props.sky) {
	                    var skyboxMaterial = props.sky.material;
	                    (skyboxMaterial) && (skyboxMaterial.path = Laya3D._addHierarchyInnerUrls(secondLevelUrls, subUrls, urlVersion, hierarchyBasePath, skyboxMaterial.path, Laya3D.MATERIAL));
	                }
	                break;
	            case "Camera":
	                var skyboxMatData = props.skyboxMaterial;
	                (skyboxMatData) && (skyboxMatData.path = Laya3D._addHierarchyInnerUrls(secondLevelUrls, subUrls, urlVersion, hierarchyBasePath, skyboxMatData.path, Laya3D.MATERIAL));
	                break;
	            case "TrailSprite3D":
	            case "MeshSprite3D":
	            case "SkinnedMeshSprite3D":
	                var meshPath = props.meshPath;
	                (meshPath) && (props.meshPath = Laya3D._addHierarchyInnerUrls(firstLevelUrls, subUrls, urlVersion, hierarchyBasePath, meshPath, Laya3D.MESH));
	                var materials = props.materials;
	                if (materials)
	                    for (i = 0, n = materials.length; i < n; i++)
	                        materials[i].path = Laya3D._addHierarchyInnerUrls(secondLevelUrls, subUrls, urlVersion, hierarchyBasePath, materials[i].path, Laya3D.MATERIAL);
	                break;
	            case "ShuriKenParticle3D":
	                var parMeshPath = props.meshPath;
	                (parMeshPath) && (props.meshPath = Laya3D._addHierarchyInnerUrls(firstLevelUrls, subUrls, urlVersion, hierarchyBasePath, parMeshPath, Laya3D.MESH));
	                props.material.path = Laya3D._addHierarchyInnerUrls(secondLevelUrls, subUrls, urlVersion, hierarchyBasePath, props.material.path, Laya3D.MATERIAL);
	                break;
	            case "Terrain":
	                Laya3D._addHierarchyInnerUrls(fourthLelUrls, subUrls, urlVersion, hierarchyBasePath, props.dataPath, Laya3D.TERRAINRES);
	                break;
	        }
	        var components = node.components;
	        if (components) {
	            for (var k = 0, p = components.length; k < p; k++) {
	                var component = components[k];
	                switch (component.type) {
	                    case "Animator":
	                        var avatarPath = component.avatarPath;
	                        var avatarData = component.avatar;
	                        (avatarData) && (avatarData.path = Laya3D._addHierarchyInnerUrls(fourthLelUrls, subUrls, urlVersion, hierarchyBasePath, avatarData.path, Laya3D.AVATAR));
	                        var clipPaths = component.clipPaths;
	                        if (!clipPaths) {
	                            var layersData = component.layers;
	                            for (i = 0; i < layersData.length; i++) {
	                                var states = layersData[i].states;
	                                for (var j = 0, m = states.length; j < m; j++) {
	                                    var clipPath = states[j].clipPath;
	                                    (clipPath) && (states[j].clipPath = Laya3D._addHierarchyInnerUrls(fourthLelUrls, subUrls, urlVersion, hierarchyBasePath, clipPath, Laya3D.ANIMATIONCLIP));
	                                }
	                            }
	                        }
	                        else {
	                            for (i = 0, n = clipPaths.length; i < n; i++)
	                                clipPaths[i] = Laya3D._addHierarchyInnerUrls(fourthLelUrls, subUrls, urlVersion, hierarchyBasePath, clipPaths[i], Laya3D.ANIMATIONCLIP);
	                        }
	                        break;
	                    case "PhysicsCollider":
	                    case "Rigidbody3D":
	                    case "CharacterController":
	                        var shapes = component.shapes;
	                        for (i = 0; i < shapes.length; i++) {
	                            var shape = shapes[i];
	                            if (shape.type === "MeshColliderShape") {
	                                var mesh = shape.mesh;
	                                (mesh) && (shape.mesh = Laya3D._addHierarchyInnerUrls(firstLevelUrls, subUrls, urlVersion, hierarchyBasePath, mesh, Laya3D.MESH));
	                            }
	                        }
	                        break;
	                }
	            }
	        }
	        var children = node.child;
	        for (i = 0, n = children.length; i < n; i++)
	            Laya3D._getSprite3DHierarchyInnerUrls(children[i], firstLevelUrls, secondLevelUrls, thirdLevelUrls, fourthLelUrls, subUrls, urlVersion, hierarchyBasePath);
	    }
	    static _loadHierarchy(loader) {
	        loader.on(Laya.Event.LOADED, null, Laya3D._onHierarchylhLoaded, [loader]);
	        loader.load(loader.url, Laya.Loader.JSON, false, null, true);
	    }
	    static _onHierarchylhLoaded(loader, lhData) {
	        var url = loader.url;
	        var urlVersion = Utils3D.getURLVerion(url);
	        var hierarchyBasePath = Laya.URL.getPath(url);
	        var firstLevUrls = [];
	        var secondLevUrls = [];
	        var thirdLevUrls = [];
	        var forthLevUrls = [];
	        var subUrls = [];
	        Laya3D._getSprite3DHierarchyInnerUrls(lhData.data, firstLevUrls, secondLevUrls, thirdLevUrls, forthLevUrls, subUrls, urlVersion, hierarchyBasePath);
	        var urlCount = firstLevUrls.length + secondLevUrls.length + forthLevUrls.length;
	        var totalProcessCount = urlCount + 1;
	        var weight = 1 / totalProcessCount;
	        Laya3D._onProcessChange(loader, 0, weight, 1.0);
	        if (forthLevUrls.length > 0) {
	            var processCeil = urlCount / totalProcessCount;
	            var processHandler = Laya.Handler.create(null, Laya3D._onProcessChange, [loader, weight, processCeil], false);
	            Laya3D._innerFourthLevelLoaderManager._create(forthLevUrls, false, Laya.Handler.create(null, Laya3D._onHierarchyInnerForthLevResouLoaded, [loader, processHandler, lhData, subUrls, firstLevUrls, secondLevUrls, thirdLevUrls, weight + processCeil * forthLevUrls.length, processCeil]), processHandler, null, null, null, 1, true);
	        }
	        else {
	            Laya3D._onHierarchyInnerForthLevResouLoaded(loader, null, lhData, subUrls, firstLevUrls, secondLevUrls, thirdLevUrls, weight, processCeil);
	        }
	    }
	    static _onHierarchyInnerForthLevResouLoaded(loader, processHandler, lhData, subUrls, firstLevUrls, secondLevUrls, thirdLevUrls, processOffset, processCeil) {
	        (processHandler) && (processHandler.recover());
	        if (thirdLevUrls.length > 0) {
	            var process = Laya.Handler.create(null, Laya3D._onProcessChange, [loader, processOffset, processCeil], false);
	            Laya3D._innerThirdLevelLoaderManager._create(thirdLevUrls, false, Laya.Handler.create(null, Laya3D._onHierarchyInnerThirdLevResouLoaded, [loader, process, lhData, subUrls, firstLevUrls, secondLevUrls, processOffset + processCeil * secondLevUrls.length, processCeil]), processHandler, null, null, null, 1, true);
	        }
	        else {
	            Laya3D._onHierarchyInnerThirdLevResouLoaded(loader, null, lhData, subUrls, firstLevUrls, secondLevUrls, processOffset, processCeil);
	        }
	    }
	    static _onHierarchyInnerThirdLevResouLoaded(loader, processHandler, lhData, subUrls, firstLevUrls, secondLevUrls, processOffset, processCeil) {
	        (processHandler) && (processHandler.recover());
	        if (secondLevUrls.length > 0) {
	            var process = Laya.Handler.create(null, Laya3D._onProcessChange, [loader, processOffset, processCeil], false);
	            Laya3D._innerSecondLevelLoaderManager._create(secondLevUrls, false, Laya.Handler.create(null, Laya3D._onHierarchyInnerSecondLevResouLoaded, [loader, process, lhData, subUrls, firstLevUrls, processOffset + processCeil * secondLevUrls.length, processCeil]), processHandler, null, null, null, 1, true);
	        }
	        else {
	            Laya3D._onHierarchyInnerSecondLevResouLoaded(loader, null, lhData, subUrls, firstLevUrls, processOffset, processCeil);
	        }
	    }
	    static _onHierarchyInnerSecondLevResouLoaded(loader, processHandler, lhData, subUrls, firstLevUrls, processOffset, processCeil) {
	        (processHandler) && (processHandler.recover());
	        if (firstLevUrls.length > 0) {
	            var process = Laya.Handler.create(null, Laya3D._onProcessChange, [loader, processOffset, processCeil], false);
	            Laya3D._innerFirstLevelLoaderManager._create(firstLevUrls, false, Laya.Handler.create(null, Laya3D._onHierarchyInnerFirstLevResouLoaded, [loader, process, lhData, subUrls]), processHandler, null, null, null, 1, true);
	        }
	        else {
	            Laya3D._onHierarchyInnerFirstLevResouLoaded(loader, null, lhData, subUrls);
	        }
	    }
	    static _onHierarchyInnerFirstLevResouLoaded(loader, processHandler, lhData, subUrls) {
	        (processHandler) && (processHandler.recover());
	        loader._cache = loader._createCache;
	        var item = lhData.data.type === "Scene3D" ? Scene3DUtils._parseScene(lhData, loader._propertyParams, loader._constructParams) : Scene3DUtils._parse(lhData, loader._propertyParams, loader._constructParams);
	        Laya3D._endLoad(loader, item, subUrls);
	    }
	    static _loadMesh(loader) {
	        loader.on(Laya.Event.LOADED, null, Laya3D._onMeshLmLoaded, [loader]);
	        loader.load(loader.url, Laya.Loader.BUFFER, false, null, true);
	    }
	    static _onMeshLmLoaded(loader, lmData) {
	        loader._cache = loader._createCache;
	        var mesh = Mesh._parse(lmData, loader._propertyParams, loader._constructParams);
	        Laya3D._endLoad(loader, mesh);
	    }
	    static _loadMaterial(loader) {
	        loader.on(Laya.Event.LOADED, null, Laya3D._onMaterilLmatLoaded, [loader]);
	        loader.load(loader.url, Laya.Loader.JSON, false, null, true);
	    }
	    static _onMaterilLmatLoaded(loader, lmatData) {
	        var url = loader.url;
	        var urlVersion = Utils3D.getURLVerion(url);
	        var materialBasePath = Laya.URL.getPath(url);
	        var urls = [];
	        var subUrls = [];
	        var customProps = lmatData.customProps;
	        var formatSubUrl;
	        var version = lmatData.version;
	        switch (version) {
	            case "LAYAMATERIAL:01":
	            case "LAYAMATERIAL:02":
	                var i, n;
	                var textures = lmatData.props.textures;
	                if (textures) {
	                    for (i = 0, n = textures.length; i < n; i++) {
	                        var tex2D = textures[i];
	                        var tex2DPath = tex2D.path;
	                        if (tex2DPath) {
	                            formatSubUrl = Laya3D.formatRelativePath(materialBasePath, tex2DPath);
	                            (urlVersion) && (formatSubUrl = formatSubUrl + urlVersion);
	                            urls.push({ url: formatSubUrl, constructParams: tex2D.constructParams, propertyParams: tex2D.propertyParams });
	                            subUrls.push(formatSubUrl);
	                            tex2D.path = formatSubUrl;
	                        }
	                    }
	                }
	                break;
	            default:
	                throw new Error("Laya3D:unkonwn version.");
	        }
	        var urlCount = urls.length;
	        var totalProcessCount = urlCount + 1;
	        var lmatWeight = 1 / totalProcessCount;
	        Laya3D._onProcessChange(loader, 0, lmatWeight, 1.0);
	        if (urlCount > 0) {
	            var processHandler = Laya.Handler.create(null, Laya3D._onProcessChange, [loader, lmatWeight, urlCount / totalProcessCount], false);
	            Laya3D._innerFourthLevelLoaderManager._create(urls, false, Laya.Handler.create(null, Laya3D._onMateialTexturesLoaded, [loader, processHandler, lmatData, subUrls]), processHandler, null, null, null, 1, true);
	        }
	        else {
	            Laya3D._onMateialTexturesLoaded(loader, null, lmatData, null);
	        }
	    }
	    static _onMateialTexturesLoaded(loader, processHandler, lmatData, subUrls) {
	        loader._cache = loader._createCache;
	        var mat = BaseMaterial._parse(lmatData, loader._propertyParams, loader._constructParams);
	        Laya3D._endLoad(loader, mat, subUrls);
	        (processHandler) && (processHandler.recover());
	    }
	    static _loadAvatar(loader) {
	        loader.on(Laya.Event.LOADED, null, function (data) {
	            loader._cache = loader._createCache;
	            var avatar = Avatar._parse(data, loader._propertyParams, loader._constructParams);
	            Laya3D._endLoad(loader, avatar);
	        });
	        loader.load(loader.url, Laya.Loader.JSON, false, null, true);
	    }
	    static _loadAnimationClip(loader) {
	        loader.on(Laya.Event.LOADED, null, function (data) {
	            loader._cache = loader._createCache;
	            var clip = AnimationClip._parse(data, loader._propertyParams, loader._constructParams);
	            Laya3D._endLoad(loader, clip);
	        });
	        loader.load(loader.url, Laya.Loader.BUFFER, false, null, true);
	    }
	    static _loadTexture2D(loader) {
	        var url = loader.url;
	        var index = url.lastIndexOf('.') + 1;
	        var verIndex = url.indexOf('?');
	        var endIndex = verIndex == -1 ? url.length : verIndex;
	        var ext = url.substr(index, endIndex - index);
	        var type;
	        switch (ext) {
	            case "jpg":
	            case "jpeg":
	            case "bmp":
	            case "gif":
	            case "png":
	                type = "nativeimage";
	                break;
	            case "dds":
	            case "ktx":
	            case "pvr":
	                type = Laya.Loader.BUFFER;
	                break;
	        }
	        loader.on(Laya.Event.LOADED, null, function (image) {
	            loader._cache = loader._createCache;
	            var tex = Laya.Texture2D._parse(image, loader._propertyParams, loader._constructParams);
	            Laya3D._endLoad(loader, tex);
	        });
	        loader.load(loader.url, type, false, null, true);
	    }
	    static _loadTextureCube(loader) {
	        loader.on(Laya.Event.LOADED, null, Laya3D._onTextureCubeLtcLoaded, [loader]);
	        loader.load(loader.url, Laya.Loader.JSON, false, null, true);
	    }
	    static _onTextureCubeLtcLoaded(loader, ltcData) {
	        var ltcBasePath = Laya.URL.getPath(loader.url);
	        var urls = [Laya3D.formatRelativePath(ltcBasePath, ltcData.front), Laya3D.formatRelativePath(ltcBasePath, ltcData.back), Laya3D.formatRelativePath(ltcBasePath, ltcData.left), Laya3D.formatRelativePath(ltcBasePath, ltcData.right), Laya3D.formatRelativePath(ltcBasePath, ltcData.up), Laya3D.formatRelativePath(ltcBasePath, ltcData.down)];
	        var ltcWeight = 1.0 / 7.0;
	        Laya3D._onProcessChange(loader, 0, ltcWeight, 1.0);
	        var processHandler = Laya.Handler.create(null, Laya3D._onProcessChange, [loader, ltcWeight, 6 / 7], false);
	        Laya3D._innerFourthLevelLoaderManager.load(urls, Laya.Handler.create(null, Laya3D._onTextureCubeImagesLoaded, [loader, urls, processHandler]), processHandler, "nativeimage");
	    }
	    static _onTextureCubeImagesLoaded(loader, urls, processHandler) {
	        var images = new Array(6);
	        for (var i = 0; i < 6; i++)
	            images[i] = Laya.Loader.getRes(urls[i]);
	        loader._cache = loader._createCache;
	        var tex = TextureCube._parse(images, loader._propertyParams, loader._constructParams);
	        processHandler.recover();
	        for (i = 0; i < 6; i++)
	            Laya.Loader.clearRes(urls[i]);
	        Laya3D._endLoad(loader, tex);
	    }
	    static _onProcessChange(loader, offset, weight, process) {
	        process = offset + process * weight;
	        (process < 1.0) && (loader.event(Laya.Event.PROGRESS, process));
	    }
	    static init(width, height, config = null, compolete = null) {
	        if (Laya3D._isInit)
	            return;
	        Laya3D._isInit = true;
	        (config) && (config.cloneTo(Config3D._config));
	        config = Config3D._config;
	        FrustumCulling.debugFrustumCulling = config.debugFrustumCulling;
	        Laya3D._editerEnvironment = config._editerEnvironment;
	        Scene3D.octreeCulling = config.octreeCulling;
	        Scene3D.octreeInitialSize = config.octreeInitialSize;
	        Scene3D.octreeInitialCenter = config.octreeInitialCenter;
	        Scene3D.octreeMinNodeSize = config.octreeMinNodeSize;
	        Scene3D.octreeLooseness = config.octreeLooseness;
	        var physics3D = window.Physics3D;
	        if (physics3D == null) {
	            Physics3D._enbalePhysics = false;
	            Laya3D.__init__(width, height, config);
	            compolete && compolete.run();
	        }
	        else {
	            Physics3D._enbalePhysics = true;
	            physics3D(config.defaultPhysicsMemory * 1024 * 1024).then(function () {
	                Laya3D.__init__(width, height, config);
	                compolete && compolete.run();
	            });
	        }
	    }
	}
	Laya3D.HIERARCHY = "HIERARCHY";
	Laya3D.MESH = "MESH";
	Laya3D.MATERIAL = "MATERIAL";
	Laya3D.TEXTURE2D = "TEXTURE2D";
	Laya3D.TEXTURECUBE = "TEXTURECUBE";
	Laya3D.ANIMATIONCLIP = "ANIMATIONCLIP";
	Laya3D.AVATAR = "AVATAR";
	Laya3D.TERRAINHEIGHTDATA = "TERRAINHEIGHTDATA";
	Laya3D.TERRAINRES = "TERRAIN";
	Laya3D._innerFirstLevelLoaderManager = new Laya.LoaderManager();
	Laya3D._innerSecondLevelLoaderManager = new Laya.LoaderManager();
	Laya3D._innerThirdLevelLoaderManager = new Laya.LoaderManager();
	Laya3D._innerFourthLevelLoaderManager = new Laya.LoaderManager();
	Laya3D._isInit = false;
	Laya3D._editerEnvironment = false;
	Laya3D.physicsSettings = new PhysicsSettings();
	window.Laya3D = Laya3D;

	class AnimatorStateScript {
	    constructor() {
	    }
	    onStateEnter() {
	    }
	    onStateUpdate() {
	    }
	    onStateExit() {
	    }
	}

	class Script3D extends Laya.Component {
	    constructor() {
	        super(...arguments);
	        this._indexInPool = -1;
	    }
	    get isSingleton() {
	        return false;
	    }
	    _checkProcessTriggers() {
	        var prototype = Script3D.prototype;
	        if (this.onTriggerEnter !== prototype.onTriggerEnter)
	            return true;
	        if (this.onTriggerStay !== prototype.onTriggerStay)
	            return true;
	        if (this.onTriggerExit !== prototype.onTriggerExit)
	            return true;
	        return false;
	    }
	    _checkProcessCollisions() {
	        var prototype = Script3D.prototype;
	        if (this.onCollisionEnter !== prototype.onCollisionEnter)
	            return true;
	        if (this.onCollisionStay !== prototype.onCollisionStay)
	            return true;
	        if (this.onCollisionExit !== prototype.onCollisionExit)
	            return true;
	        return false;
	    }
	    _onAwake() {
	        this.onAwake();
	        if (this.onStart !== Script3D.prototype.onStart)
	            Laya.Laya.startTimer.callLater(this, this.onStart);
	    }
	    _onEnable() {
	        this.owner._scene._addScript(this);
	        var proto = Script3D.prototype;
	        if (this.onKeyDown !== proto.onKeyDown) {
	            Laya.Laya.stage.on(Laya.Event.KEY_DOWN, this, this.onKeyDown);
	        }
	        if (this.onKeyPress !== proto.onKeyPress) {
	            Laya.Laya.stage.on(Laya.Event.KEY_PRESS, this, this.onKeyUp);
	        }
	        if (this.onKeyUp !== proto.onKeyUp) {
	            Laya.Laya.stage.on(Laya.Event.KEY_UP, this, this.onKeyUp);
	        }
	    }
	    _onDisable() {
	        this.owner._scene._removeScript(this);
	        this.owner.offAllCaller(this);
	        Laya.Laya.stage.offAllCaller(this);
	    }
	    _isScript() {
	        return true;
	    }
	    _onAdded() {
	        var sprite = this.owner;
	        var scripts = sprite._scripts;
	        scripts || (sprite._scripts = scripts = []);
	        scripts.push(this);
	        if (!sprite._needProcessCollisions)
	            sprite._needProcessCollisions = this._checkProcessCollisions();
	        if (!sprite._needProcessTriggers)
	            sprite._needProcessTriggers = this._checkProcessTriggers();
	    }
	    _onDestroy() {
	        var scripts = this.owner._scripts;
	        scripts.splice(scripts.indexOf(this), 1);
	        var sprite = this.owner;
	        sprite._needProcessTriggers = false;
	        for (var i = 0, n = scripts.length; i < n; i++) {
	            if (scripts[i]._checkProcessTriggers()) {
	                sprite._needProcessTriggers = true;
	                break;
	            }
	        }
	        sprite._needProcessCollisions = false;
	        for (i = 0, n = scripts.length; i < n; i++) {
	            if (scripts[i]._checkProcessCollisions()) {
	                sprite._needProcessCollisions = true;
	                break;
	            }
	        }
	        this.onDestroy();
	    }
	    onAwake() {
	    }
	    onEnable() {
	    }
	    onStart() {
	    }
	    onTriggerEnter(other) {
	    }
	    onTriggerStay(other) {
	    }
	    onTriggerExit(other) {
	    }
	    onCollisionEnter(collision) {
	    }
	    onCollisionStay(collision) {
	    }
	    onCollisionExit(collision) {
	    }
	    onMouseDown() {
	    }
	    onMouseDrag() {
	    }
	    onMouseClick() {
	    }
	    onMouseUp() {
	    }
	    onMouseEnter() {
	    }
	    onMouseOver() {
	    }
	    onMouseOut() {
	    }
	    onKeyDown(e) {
	    }
	    onKeyPress(e) {
	    }
	    onKeyUp(e) {
	    }
	    onUpdate() {
	    }
	    onLateUpdate() {
	    }
	    onPreRender() {
	    }
	    onPostRender() {
	    }
	    onDisable() {
	    }
	    onDestroy() {
	    }
	}

	class HeightMap {
	    constructor(width, height, minHeight, maxHeight) {
	        this._datas = [];
	        this._w = width;
	        this._h = height;
	        this._minHeight = minHeight;
	        this._maxHeight = maxHeight;
	    }
	    static creatFromMesh(mesh, width, height, outCellSize) {
	        var vertices = [];
	        var indexs = [];
	        var submesheCount = mesh.subMeshCount;
	        for (var i = 0; i < submesheCount; i++) {
	            var subMesh = mesh.getSubMesh(i);
	            var vertexBuffer = subMesh._vertexBuffer;
	            var verts = vertexBuffer.getFloat32Data();
	            var subMeshVertices = [];
	            for (var j = 0; j < verts.length; j += vertexBuffer.vertexDeclaration.vertexStride / 4) {
	                var position = new Vector3(verts[j + 0], verts[j + 1], verts[j + 2]);
	                subMeshVertices.push(position);
	            }
	            vertices.push(subMeshVertices);
	            var ib = subMesh._indexBuffer;
	            indexs.push(ib.getData());
	        }
	        var bounds = mesh.bounds;
	        var minX = bounds.getMin().x;
	        var minZ = bounds.getMin().z;
	        var maxX = bounds.getMax().x;
	        var maxZ = bounds.getMax().z;
	        var minY = bounds.getMin().y;
	        var maxY = bounds.getMax().y;
	        var widthSize = maxX - minX;
	        var heightSize = maxZ - minZ;
	        var cellWidth = outCellSize.x = widthSize / (width - 1);
	        var cellHeight = outCellSize.y = heightSize / (height - 1);
	        var heightMap = new HeightMap(width, height, minY, maxY);
	        var ray = HeightMap._tempRay;
	        var rayDir = ray.direction;
	        rayDir.x = 0;
	        rayDir.y = -1;
	        rayDir.z = 0;
	        const heightOffset = 0.1;
	        var rayY = maxY + heightOffset;
	        ray.origin.y = rayY;
	        for (var h = 0; h < height; h++) {
	            var posZ = minZ + h * cellHeight;
	            heightMap._datas[h] = [];
	            for (var w = 0; w < width; w++) {
	                var posX = minX + w * cellWidth;
	                var rayOri = ray.origin;
	                rayOri.x = posX;
	                rayOri.z = posZ;
	                var closestIntersection = HeightMap._getPosition(ray, vertices, indexs);
	                heightMap._datas[h][w] = (closestIntersection === Number.MAX_VALUE) ? NaN : rayY - closestIntersection;
	            }
	        }
	        return heightMap;
	    }
	    static createFromImage(texture, minHeight, maxHeight) {
	        var textureWidth = texture.width;
	        var textureHeight = texture.height;
	        var heightMap = new HeightMap(textureWidth, textureHeight, minHeight, maxHeight);
	        var compressionRatio = (maxHeight - minHeight) / 254;
	        var pixelsInfo = texture.getPixels();
	        var index = 0;
	        for (var h = 0; h < textureHeight; h++) {
	            var colDatas = heightMap._datas[h] = [];
	            for (var w = 0; w < textureWidth; w++) {
	                var r = pixelsInfo[index++];
	                var g = pixelsInfo[index++];
	                var b = pixelsInfo[index++];
	                var a = pixelsInfo[index++];
	                if (r == 255 && g == 255 && b == 255 && a == 255)
	                    colDatas[w] = NaN;
	                else {
	                    colDatas[w] = (r + g + b) / 3 * compressionRatio + minHeight;
	                }
	            }
	        }
	        return heightMap;
	    }
	    static _getPosition(ray, vertices, indexs) {
	        var closestIntersection = Number.MAX_VALUE;
	        for (var i = 0; i < vertices.length; i++) {
	            var subMeshVertices = vertices[i];
	            var subMeshIndexes = indexs[i];
	            for (var j = 0; j < subMeshIndexes.length; j += 3) {
	                var vertex1 = subMeshVertices[subMeshIndexes[j + 0]];
	                var vertex2 = subMeshVertices[subMeshIndexes[j + 1]];
	                var vertex3 = subMeshVertices[subMeshIndexes[j + 2]];
	                var intersection = Picker.rayIntersectsTriangle(ray, vertex1, vertex2, vertex3);
	                if (!isNaN(intersection) && intersection < closestIntersection) {
	                    closestIntersection = intersection;
	                }
	            }
	        }
	        return closestIntersection;
	    }
	    get width() {
	        return this._w;
	    }
	    get height() {
	        return this._h;
	    }
	    get maxHeight() {
	        return this._maxHeight;
	    }
	    get minHeight() {
	        return this._minHeight;
	    }
	    _inBounds(row, col) {
	        return row >= 0 && row < this._h && col >= 0 && col < this._w;
	    }
	    getHeight(row, col) {
	        if (this._inBounds(row, col))
	            return this._datas[row][col];
	        else
	            return NaN;
	    }
	}
	HeightMap._tempRay = new Ray(new Vector3(), new Vector3());

	class MeshTerrainSprite3D extends MeshSprite3D {
	    constructor(mesh, heightMap, name = null) {
	        super(mesh, name);
	        this._heightMap = heightMap;
	        this._cellSize = new Vector2();
	    }
	    static createFromMesh(mesh, heightMapWidth, heightMapHeight, name = null) {
	        var meshTerrainSprite3D = new MeshTerrainSprite3D(mesh, null, name);
	        meshTerrainSprite3D._initCreateFromMesh(heightMapWidth, heightMapHeight);
	        return meshTerrainSprite3D;
	    }
	    static createFromMeshAndHeightMap(mesh, texture, minHeight, maxHeight, name = null) {
	        var meshTerrainSprite3D = new MeshTerrainSprite3D(mesh, null, name);
	        meshTerrainSprite3D._initCreateFromMeshHeightMap(texture, minHeight, maxHeight);
	        return meshTerrainSprite3D;
	    }
	    get minX() {
	        var worldMat = this.transform.worldMatrix;
	        var worldMatE = worldMat.elements;
	        return this._minX * this._getScaleX() + worldMatE[12];
	    }
	    get minZ() {
	        var worldMat = this.transform.worldMatrix;
	        var worldMatE = worldMat.elements;
	        return this._minZ * this._getScaleZ() + worldMatE[14];
	    }
	    get width() {
	        return (this._heightMap.width - 1) * this._cellSize.x * this._getScaleX();
	    }
	    get depth() {
	        return (this._heightMap.height - 1) * this._cellSize.y * this._getScaleZ();
	    }
	    _disableRotation() {
	        var rotation = this.transform.rotation;
	        rotation.x = 0;
	        rotation.y = 0;
	        rotation.z = 0;
	        rotation.w = 1;
	        this.transform.rotation = rotation;
	    }
	    _getScaleX() {
	        var worldMat = this.transform.worldMatrix;
	        var worldMatE = worldMat.elements;
	        var m11 = worldMatE[0];
	        var m12 = worldMatE[1];
	        var m13 = worldMatE[2];
	        return Math.sqrt((m11 * m11) + (m12 * m12) + (m13 * m13));
	    }
	    _getScaleZ() {
	        var worldMat = this.transform.worldMatrix;
	        var worldMatE = worldMat.elements;
	        var m31 = worldMatE[8];
	        var m32 = worldMatE[9];
	        var m33 = worldMatE[10];
	        return Math.sqrt((m31 * m31) + (m32 * m32) + (m33 * m33));
	    }
	    _initCreateFromMesh(heightMapWidth, heightMapHeight) {
	        this._heightMap = HeightMap.creatFromMesh(this.meshFilter.sharedMesh, heightMapWidth, heightMapHeight, this._cellSize);
	        var boundingBox = this.meshFilter.sharedMesh.bounds;
	        var min = boundingBox.getMin();
	        var max = boundingBox.getMax();
	        this._minX = min.x;
	        this._minZ = min.z;
	    }
	    _initCreateFromMeshHeightMap(texture, minHeight, maxHeight) {
	        var boundingBox = this.meshFilter.sharedMesh.bounds;
	        this._heightMap = HeightMap.createFromImage(texture, minHeight, maxHeight);
	        this._computeCellSize(boundingBox);
	        var min = boundingBox.getMin();
	        var max = boundingBox.getMax();
	        this._minX = min.x;
	        this._minZ = min.z;
	    }
	    _computeCellSize(boundingBox) {
	        var min = boundingBox.getMin();
	        var max = boundingBox.getMax();
	        var minX = min.x;
	        var minZ = min.z;
	        var maxX = max.x;
	        var maxZ = max.z;
	        var widthSize = maxX - minX;
	        var heightSize = maxZ - minZ;
	        this._cellSize.x = widthSize / (this._heightMap.width - 1);
	        this._cellSize.y = heightSize / (this._heightMap.height - 1);
	    }
	    _update(state) {
	        this._disableRotation();
	    }
	    getHeight(x, z) {
	        MeshTerrainSprite3D._tempVector3.x = x;
	        MeshTerrainSprite3D._tempVector3.y = 0;
	        MeshTerrainSprite3D._tempVector3.z = z;
	        this._disableRotation();
	        var worldMat = this.transform.worldMatrix;
	        worldMat.invert(MeshTerrainSprite3D._tempMatrix4x4);
	        Vector3.transformCoordinate(MeshTerrainSprite3D._tempVector3, MeshTerrainSprite3D._tempMatrix4x4, MeshTerrainSprite3D._tempVector3);
	        x = MeshTerrainSprite3D._tempVector3.x;
	        z = MeshTerrainSprite3D._tempVector3.z;
	        var c = (x - this._minX) / this._cellSize.x;
	        var d = (z - this._minZ) / this._cellSize.y;
	        var row = Math.floor(d);
	        var col = Math.floor(c);
	        var s = c - col;
	        var t = d - row;
	        var uy;
	        var vy;
	        var worldMatE = worldMat.elements;
	        var m21 = worldMatE[4];
	        var m22 = worldMatE[5];
	        var m23 = worldMatE[6];
	        var scaleY = Math.sqrt((m21 * m21) + (m22 * m22) + (m23 * m23));
	        var translateY = worldMatE[13];
	        var h01 = this._heightMap.getHeight(row, col + 1);
	        var h10 = this._heightMap.getHeight((row + 1), col);
	        if (isNaN(h01) || isNaN(h10))
	            return NaN;
	        if (s + t <= 1.0) {
	            var h00 = this._heightMap.getHeight(row, col);
	            if (isNaN(h00))
	                return NaN;
	            uy = h01 - h00;
	            vy = h10 - h00;
	            return (h00 + s * uy + t * vy) * scaleY + translateY;
	        }
	        else {
	            var h11 = this._heightMap.getHeight((row + 1), col + 1);
	            if (isNaN(h11))
	                return NaN;
	            uy = h10 - h11;
	            vy = h01 - h11;
	            return (h11 + (1.0 - s) * uy + (1.0 - t) * vy) * scaleY + translateY;
	        }
	    }
	}
	MeshTerrainSprite3D._tempVector3 = new Vector3();
	MeshTerrainSprite3D._tempMatrix4x4 = new Matrix4x4();

	class GradientDataVector2 {
	    constructor() {
	        this._currentLength = 0;
	        this._elements = new Float32Array(12);
	    }
	    get gradientCount() {
	        return this._currentLength / 3;
	    }
	    add(key, value) {
	        if (this._currentLength < 8) {
	            if ((this._currentLength === 6) && ((key !== 1))) {
	                key = 1;
	                console.log("GradientDataVector2 warning:the forth key is  be force set to 1.");
	            }
	            this._elements[this._currentLength++] = key;
	            this._elements[this._currentLength++] = value.x;
	            this._elements[this._currentLength++] = value.y;
	        }
	        else {
	            console.log("GradientDataVector2 warning:data count must lessEqual than 4");
	        }
	    }
	    cloneTo(destObject) {
	        var destGradientDataVector2 = destObject;
	        destGradientDataVector2._currentLength = this._currentLength;
	        var destElements = destGradientDataVector2._elements;
	        for (var i = 0, n = this._elements.length; i < n; i++) {
	            destElements[i] = this._elements[i];
	        }
	    }
	    clone() {
	        var destGradientDataVector2 = new GradientDataVector2();
	        this.cloneTo(destGradientDataVector2);
	        return destGradientDataVector2;
	    }
	}

	class PixelLineData {
	    constructor() {
	        this.startPosition = new Vector3();
	        this.endPosition = new Vector3();
	        this.startColor = new Color();
	        this.endColor = new Color();
	    }
	    cloneTo(destObject) {
	        this.startPosition.cloneTo(destObject.startPosition);
	        this.endPosition.cloneTo(destObject.endPosition);
	        this.startColor.cloneTo(destObject.startColor);
	        this.endColor.cloneTo(destObject.endColor);
	    }
	}

	class PostProcessEffect {
	    constructor() {
	    }
	    render(context) {
	    }
	}

	class BloomEffect extends PostProcessEffect {
	    constructor() {
	        super();
	        this._shader = null;
	        this._shaderData = new ShaderData();
	        this._linearColor = new Color();
	        this._bloomTextureTexelSize = new Vector4();
	        this._shaderThreshold = new Vector4();
	        this._shaderParams = new Vector4();
	        this._pyramid = null;
	        this._intensity = 0.0;
	        this._threshold = 1.0;
	        this._softKnee = 0.5;
	        this._diffusion = 7.0;
	        this._anamorphicRatio = 0.0;
	        this._dirtIntensity = 0.0;
	        this._shaderSetting = new Vector4();
	        this._dirtTileOffset = new Vector4();
	        this.clamp = 65472.0;
	        this.color = new Color(1.0, 1.0, 1.0, 1.0);
	        this.fastMode = false;
	        this.dirtTexture = null;
	        this._shader = Shader3D.find("PostProcessBloom");
	        this._pyramid = new Array(BloomEffect.MAXPYRAMIDSIZE * 2);
	    }
	    get intensity() {
	        return this._intensity;
	    }
	    set intensity(value) {
	        this._intensity = Math.max(value, 0.0);
	    }
	    get threshold() {
	        return this._threshold;
	    }
	    set threshold(value) {
	        this._threshold = Math.max(value, 0.0);
	    }
	    get softKnee() {
	        return this._softKnee;
	    }
	    set softKnee(value) {
	        this._softKnee = Math.min(Math.max(value, 0.0), 1.0);
	    }
	    get diffusion() {
	        return this._diffusion;
	    }
	    set diffusion(value) {
	        this._diffusion = Math.min(Math.max(value, 1), 10);
	    }
	    get anamorphicRatio() {
	        return this._anamorphicRatio;
	    }
	    set anamorphicRatio(value) {
	        this._anamorphicRatio = Math.min(Math.max(value, -1.0), 1.0);
	    }
	    get dirtIntensity() {
	        return this._dirtIntensity;
	    }
	    set dirtIntensity(value) {
	        this._dirtIntensity = Math.max(value, 0.0);
	    }
	    render(context) {
	        var cmd = context.command;
	        var viewport = context.camera.viewport;
	        this._shaderData.setTexture(BloomEffect.SHADERVALUE_AUTOEXPOSURETEX, Laya.Texture2D.whiteTexture);
	        var ratio = this._anamorphicRatio;
	        var rw = ratio < 0 ? -ratio : 0;
	        var rh = ratio > 0 ? ratio : 0;
	        var tw = Math.floor(viewport.width / (2 - rw));
	        var th = Math.floor(viewport.height / (2 - rh));
	        var s = Math.max(tw, th);
	        var logs;
	        logs = Math.log2(s) + this._diffusion - 10;
	        var logsInt = Math.floor(logs);
	        var iterations = Math.min(Math.max(logsInt, 1), BloomEffect.MAXPYRAMIDSIZE);
	        var sampleScale = 0.5 + logs - logsInt;
	        this._shaderData.setNumber(BloomEffect.SHADERVALUE_SAMPLESCALE, sampleScale);
	        var lthresh = Color.gammaToLinearSpace(this.threshold);
	        var knee = lthresh * this._softKnee + 1e-5;
	        this._shaderThreshold.setValue(lthresh, lthresh - knee, knee * 2, 0.25 / knee);
	        this._shaderData.setVector(BloomEffect.SHADERVALUE_THRESHOLD, this._shaderThreshold);
	        var lclamp = Color.gammaToLinearSpace(this.clamp);
	        this._shaderParams.setValue(lclamp, 0, 0, 0);
	        this._shaderData.setVector(BloomEffect.SHADERVALUE_PARAMS, this._shaderParams);
	        var qualityOffset = this.fastMode ? 1 : 0;
	        var lastDownTexture = context.source;
	        for (var i = 0; i < iterations; i++) {
	            var downIndex = i * 2;
	            var upIndex = downIndex + 1;
	            var subShader = i == 0 ? BloomEffect.SUBSHADER_PREFILTER13 + qualityOffset : BloomEffect.SUBSHADER_DOWNSAMPLE13 + qualityOffset;
	            var mipDownTexture = RenderTexture.createFromPool(tw, th, Laya.RenderTextureFormat.R8G8B8, Laya.RenderTextureDepthFormat.DEPTHSTENCIL_NONE, Laya.BaseTexture.FILTERMODE_BILINEAR);
	            this._pyramid[downIndex] = mipDownTexture;
	            if (i !== iterations - 1) {
	                var mipUpTexture = RenderTexture.createFromPool(tw, th, Laya.RenderTextureFormat.R8G8B8, Laya.RenderTextureDepthFormat.DEPTHSTENCIL_NONE, Laya.BaseTexture.FILTERMODE_BILINEAR);
	                this._pyramid[upIndex] = mipUpTexture;
	            }
	            cmd.blitScreenTriangle(lastDownTexture, mipDownTexture, this._shader, this._shaderData, subShader);
	            lastDownTexture = mipDownTexture;
	            tw = Math.max(Math.floor(tw / 2), 1);
	            th = Math.max(Math.floor(th / 2), 1);
	        }
	        var lastUpTexture = this._pyramid[(iterations - 1) * 2];
	        for (i = iterations - 2; i >= 0; i--) {
	            downIndex = i * 2;
	            upIndex = downIndex + 1;
	            mipDownTexture = this._pyramid[downIndex];
	            mipUpTexture = this._pyramid[upIndex];
	            cmd.setShaderDataTexture(this._shaderData, BloomEffect.SHADERVALUE_BLOOMTEX, mipDownTexture);
	            cmd.blitScreenTriangle(lastUpTexture, mipUpTexture, this._shader, this._shaderData, BloomEffect.SUBSHADER_UPSAMPLETENT + qualityOffset);
	            lastUpTexture = mipUpTexture;
	        }
	        var linearColor = this._linearColor;
	        this.color.toLinear(linearColor);
	        var intensity = Math.pow(2, this._intensity / 10.0) - 1.0;
	        var shaderSettings = this._shaderSetting;
	        this._shaderSetting.setValue(sampleScale, intensity, this._dirtIntensity, iterations);
	        var dirtTexture = this.dirtTexture ? this.dirtTexture : Laya.Texture2D.blackTexture;
	        var dirtRatio = dirtTexture.width / dirtTexture.height;
	        var screenRatio = viewport.width / viewport.height;
	        var dirtTileOffset = this._dirtTileOffset;
	        if (dirtRatio > screenRatio)
	            dirtTileOffset.setValue(screenRatio / dirtRatio, 1.0, (1.0 - dirtTileOffset.x) * 0.5, 0.0);
	        else if (dirtRatio < screenRatio)
	            dirtTileOffset.setValue(1.0, dirtRatio / screenRatio, 0.0, (1.0 - dirtTileOffset.y) * 0.5);
	        var compositeShaderData = context.compositeShaderData;
	        if (this.fastMode)
	            compositeShaderData.addDefine(PostProcess.SHADERDEFINE_BLOOM_LOW);
	        else
	            compositeShaderData.addDefine(PostProcess.SHADERDEFINE_BLOOM);
	        this._bloomTextureTexelSize.setValue(1.0 / lastUpTexture.width, 1.0 / lastUpTexture.height, lastUpTexture.width, lastUpTexture.height);
	        compositeShaderData.setVector(PostProcess.SHADERVALUE_BLOOM_DIRTTILEOFFSET, dirtTileOffset);
	        compositeShaderData.setVector(PostProcess.SHADERVALUE_BLOOM_SETTINGS, shaderSettings);
	        compositeShaderData.setVector(PostProcess.SHADERVALUE_BLOOM_COLOR, new Vector4(linearColor.r, linearColor.g, linearColor.b, linearColor.a));
	        compositeShaderData.setTexture(PostProcess.SHADERVALUE_BLOOM_DIRTTEX, dirtTexture);
	        compositeShaderData.setTexture(PostProcess.SHADERVALUE_BLOOMTEX, lastUpTexture);
	        compositeShaderData.setVector(PostProcess.SHADERVALUE_BLOOMTEX_TEXELSIZE, this._bloomTextureTexelSize);
	        for (i = 0; i < iterations; i++) {
	            downIndex = i * 2;
	            upIndex = downIndex + 1;
	            RenderTexture.recoverToPool(this._pyramid[downIndex]);
	            (i !== 0 && i !== iterations - 1) && (RenderTexture.recoverToPool(this._pyramid[upIndex]));
	        }
	        context.deferredReleaseTextures.push(lastUpTexture);
	    }
	}
	BloomEffect.SHADERVALUE_MAINTEX = Shader3D.propertyNameToID("u_MainTex");
	BloomEffect.SHADERVALUE_AUTOEXPOSURETEX = Shader3D.propertyNameToID("u_AutoExposureTex");
	BloomEffect.SHADERVALUE_SAMPLESCALE = Shader3D.propertyNameToID("u_SampleScale");
	BloomEffect.SHADERVALUE_THRESHOLD = Shader3D.propertyNameToID("u_Threshold");
	BloomEffect.SHADERVALUE_PARAMS = Shader3D.propertyNameToID("u_Params");
	BloomEffect.SHADERVALUE_BLOOMTEX = Shader3D.propertyNameToID("u_BloomTex");
	BloomEffect.SUBSHADER_PREFILTER13 = 0;
	BloomEffect.SUBSHADER_PREFILTER4 = 1;
	BloomEffect.SUBSHADER_DOWNSAMPLE13 = 2;
	BloomEffect.SUBSHADER_DOWNSAMPLE4 = 3;
	BloomEffect.SUBSHADER_UPSAMPLETENT = 4;
	BloomEffect.SUBSHADER_UPSAMPLEBOX = 5;
	BloomEffect.MAXPYRAMIDSIZE = 16;

	class SceneManager {
	    constructor() {
	    }
	}

	class RandX {
	    constructor(seed) {
	        if (!(seed instanceof Array) || seed.length !== 4)
	            throw new Error('Rand:Seed must be an array with 4 numbers');
	        this._state0U = seed[0] | 0;
	        this._state0L = seed[1] | 0;
	        this._state1U = seed[2] | 0;
	        this._state1L = seed[3] | 0;
	    }
	    randomint() {
	        var s1U = this._state0U, s1L = this._state0L;
	        var s0U = this._state1U, s0L = this._state1L;
	        var sumL = (s0L >>> 0) + (s1L >>> 0);
	        var resU = (s0U + s1U + (sumL / 2 >>> 31)) >>> 0;
	        var resL = sumL >>> 0;
	        this._state0U = s0U;
	        this._state0L = s0L;
	        var t1U = 0, t1L = 0;
	        var t2U = 0, t2L = 0;
	        var a1 = 23;
	        var m1 = 0xFFFFFFFF << (32 - a1);
	        t1U = (s1U << a1) | ((s1L & m1) >>> (32 - a1));
	        t1L = s1L << a1;
	        s1U = s1U ^ t1U;
	        s1L = s1L ^ t1L;
	        t1U = s1U ^ s0U;
	        t1L = s1L ^ s0L;
	        var a2 = 18;
	        var m2 = 0xFFFFFFFF >>> (32 - a2);
	        t2U = s1U >>> a2;
	        t2L = (s1L >>> a2) | ((s1U & m2) << (32 - a2));
	        t1U = t1U ^ t2U;
	        t1L = t1L ^ t2L;
	        var a3 = 5;
	        var m3 = 0xFFFFFFFF >>> (32 - a3);
	        t2U = s0U >>> a3;
	        t2L = (s0L >>> a3) | ((s0U & m3) << (32 - a3));
	        t1U = t1U ^ t2U;
	        t1L = t1L ^ t2L;
	        this._state1U = t1U;
	        this._state1L = t1L;
	        return [resU, resL];
	    }
	    random() {
	        var t2 = this.randomint();
	        var t2U = t2[0];
	        var t2L = t2[1];
	        var eU = 0x3FF << (52 - 32);
	        var eL = 0;
	        var a1 = 12;
	        var m1 = 0xFFFFFFFF >>> (32 - a1);
	        var sU = t2U >>> a1;
	        var sL = (t2L >>> a1) | ((t2U & m1) << (32 - a1));
	        var xU = eU | sU;
	        var xL = eL | sL;
	        RandX._CONVERTION_BUFFER.setUint32(0, xU, false);
	        RandX._CONVERTION_BUFFER.setUint32(4, xL, false);
	        var d = RandX._CONVERTION_BUFFER.getFloat64(0, false);
	        return d - 1;
	    }
	}
	RandX._CONVERTION_BUFFER = new DataView(new ArrayBuffer(8));
	RandX.defaultRand = new RandX([0, Date.now() / 65536, 0, Date.now() % 65536]);

	class Constraint3D {
	    constructor() {
	    }
	}

	class ConstraintComponent extends Laya.Component {
	    constructor() {
	        super();
	        this._feedbackEnabled = false;
	    }
	    get enabled() {
	        return super.enabled;
	    }
	    set enabled(value) {
	        this._nativeConstraint.IsEnabled = value;
	        super.enabled = value;
	    }
	    get breakingImpulseThreshold() {
	        return this._breakingImpulseThreshold;
	    }
	    set breakingImpulseThreshold(value) {
	        this._nativeConstraint.BreakingImpulseThreshold = value;
	        this._breakingImpulseThreshold = value;
	    }
	    get appliedImpulse() {
	        if (!this._feedbackEnabled) {
	            this._nativeConstraint.EnableFeedback(true);
	            this._feedbackEnabled = true;
	        }
	        return this._nativeConstraint.AppliedImpulse;
	    }
	    get connectedBody() {
	        return this._connectedBody;
	    }
	    set connectedBody(value) {
	        this._connectedBody = value;
	    }
	    _onDestroy() {
	        var physics3D = Physics3D._physics3D;
	        physics3D.destroy(this._nativeConstraint);
	        this._nativeConstraint = null;
	    }
	}

	class Point2PointConstraint {
	    constructor() {
	        this._pivotInA = new Vector3();
	        this._pivotInB = new Vector3();
	    }
	    get pivotInA() {
	        return this._pivotInA;
	    }
	    set pivotInA(value) {
	        this._pivotInA = value;
	    }
	    get pivotInB() {
	        return this._pivotInB;
	    }
	    set pivotInB(value) {
	        this._pivotInB = value;
	    }
	    get damping() {
	        return this._damping;
	    }
	    set damping(value) {
	        this._damping = value;
	    }
	    get impulseClamp() {
	        return this._impulseClamp;
	    }
	    set impulseClamp(value) {
	        this._impulseClamp = value;
	    }
	    get tau() {
	        return this._tau;
	    }
	    set tau(value) {
	        this._tau = value;
	    }
	}

	class HeightfieldColliderShape {
	    constructor() {
	    }
	}

	class TextMesh {
	    get text() {
	        return this._text;
	    }
	    set text(value) {
	        this._text = value;
	    }
	    get fontSize() {
	        return this._fontSize;
	    }
	    set fontSize(value) {
	        this._fontSize = value;
	    }
	    get color() {
	        return this._color;
	    }
	    set color(value) {
	        this._color = value;
	    }
	    constructor() {
	    }
	    _createVertexBuffer(charCount) {
	    }
	    _resizeVertexBuffer(charCount) {
	    }
	    _addChar() {
	    }
	}

	class Size {
	    constructor(width, height) {
	        this._width = 0;
	        this._height = 0;
	        this._width = width;
	        this._height = height;
	    }
	    static get fullScreen() {
	        return new Size(-1, -1);
	    }
	    get width() {
	        if (this._width === -1)
	            return RenderContext3D.clientWidth;
	        return this._width;
	    }
	    get height() {
	        if (this._height === -1)
	            return RenderContext3D.clientHeight;
	        return this._height;
	    }
	}

	exports.AlternateLightQueue = AlternateLightQueue;
	exports.AnimationClip = AnimationClip;
	exports.AnimationClipParser03 = AnimationClipParser03;
	exports.AnimationClipParser04 = AnimationClipParser04;
	exports.AnimationEvent = AnimationEvent;
	exports.AnimationNode = AnimationNode;
	exports.AnimationTransform3D = AnimationTransform3D;
	exports.Animator = Animator;
	exports.AnimatorControllerLayer = AnimatorControllerLayer;
	exports.AnimatorPlayState = AnimatorPlayState;
	exports.AnimatorState = AnimatorState;
	exports.AnimatorStateScript = AnimatorStateScript;
	exports.Avatar = Avatar;
	exports.BaseCamera = BaseCamera;
	exports.BaseMaterial = BaseMaterial;
	exports.BaseRender = BaseRender;
	exports.BaseShape = BaseShape;
	exports.BatchMark = BatchMark;
	exports.BlinnPhongMaterial = BlinnPhongMaterial;
	exports.BlitScreenQuadCMD = BlitScreenQuadCMD;
	exports.BloomEffect = BloomEffect;
	exports.BoundBox = BoundBox;
	exports.BoundFrustum = BoundFrustum;
	exports.BoundSphere = BoundSphere;
	exports.Bounds = Bounds;
	exports.BoundsOctree = BoundsOctree;
	exports.BoundsOctreeNode = BoundsOctreeNode;
	exports.BoxColliderShape = BoxColliderShape;
	exports.BoxShape = BoxShape;
	exports.BufferState = BufferState;
	exports.Burst = Burst;
	exports.Camera = Camera;
	exports.CapsuleColliderShape = CapsuleColliderShape;
	exports.CastShadowList = CastShadowList;
	exports.CharacterController = CharacterController;
	exports.CircleShape = CircleShape;
	exports.Cluster = Cluster;
	exports.ColliderShape = ColliderShape;
	exports.Collision = Collision;
	exports.CollisionTool = CollisionTool;
	exports.CollisionUtils = CollisionUtils;
	exports.Color = Color;
	exports.ColorOverLifetime = ColorOverLifetime;
	exports.Command = Command;
	exports.CommandBuffer = CommandBuffer;
	exports.CompoundColliderShape = CompoundColliderShape;
	exports.ConchQuaternion = ConchQuaternion;
	exports.ConchVector3 = ConchVector3;
	exports.ConchVector4 = ConchVector4;
	exports.ConeColliderShape = ConeColliderShape;
	exports.ConeShape = ConeShape;
	exports.Config3D = Config3D;
	exports.Constraint3D = Constraint3D;
	exports.ConstraintComponent = ConstraintComponent;
	exports.ContactPoint = ContactPoint;
	exports.ContainmentType = ContainmentType;
	exports.CylinderColliderShape = CylinderColliderShape;
	exports.DefineDatas = DefineDatas;
	exports.DirectionLight = DirectionLight;
	exports.DirectionLightQueue = DirectionLightQueue;
	exports.DynamicBatchManager = DynamicBatchManager;
	exports.EffectMaterial = EffectMaterial;
	exports.Emission = Emission;
	exports.ExtendTerrainMaterial = ExtendTerrainMaterial;
	exports.FloatKeyframe = FloatKeyframe;
	exports.FrameOverTime = FrameOverTime;
	exports.FrustumCulling = FrustumCulling;
	exports.GeometryElement = GeometryElement;
	exports.Gradient = Gradient;
	exports.GradientAngularVelocity = GradientAngularVelocity;
	exports.GradientColor = GradientColor;
	exports.GradientDataInt = GradientDataInt;
	exports.GradientDataNumber = GradientDataNumber;
	exports.GradientDataVector2 = GradientDataVector2;
	exports.GradientMode = GradientMode;
	exports.GradientSize = GradientSize;
	exports.GradientVelocity = GradientVelocity;
	exports.HalfFloatUtils = HalfFloatUtils;
	exports.HeightMap = HeightMap;
	exports.HeightfieldColliderShape = HeightfieldColliderShape;
	exports.HemisphereShape = HemisphereShape;
	exports.HitResult = HitResult;
	exports.ILaya3D = ILaya3D;
	exports.IndexBuffer3D = IndexBuffer3D;
	exports.Input3D = Input3D;
	exports.Keyframe = Keyframe;
	exports.KeyframeNode = KeyframeNode;
	exports.KeyframeNodeList = KeyframeNodeList;
	exports.KeyframeNodeOwner = KeyframeNodeOwner;
	exports.Laya3D = Laya3D;
	exports.LightQueue = LightQueue;
	exports.LightSprite = LightSprite;
	exports.LoadModelV04 = LoadModelV04;
	exports.LoadModelV05 = LoadModelV05;
	exports.MathUtils3D = MathUtils3D;
	exports.Matrix3x3 = Matrix3x3;
	exports.Matrix4x4 = Matrix4x4;
	exports.Mesh = Mesh;
	exports.MeshColliderShape = MeshColliderShape;
	exports.MeshFilter = MeshFilter;
	exports.MeshReader = MeshReader;
	exports.MeshRenderDynamicBatchManager = MeshRenderDynamicBatchManager;
	exports.MeshRenderStaticBatchManager = MeshRenderStaticBatchManager;
	exports.MeshRenderer = MeshRenderer;
	exports.MeshSprite3D = MeshSprite3D;
	exports.MeshSprite3DShaderDeclaration = MeshSprite3DShaderDeclaration;
	exports.MeshTerrainSprite3D = MeshTerrainSprite3D;
	exports.MouseTouch = MouseTouch;
	exports.OctreeMotionList = OctreeMotionList;
	exports.PBRSpecularMaterial = PBRSpecularMaterial;
	exports.PBRStandardMaterial = PBRStandardMaterial;
	exports.ParallelSplitShadowMap = ParallelSplitShadowMap;
	exports.Physics3D = Physics3D;
	exports.Physics3DUtils = Physics3DUtils;
	exports.PhysicsCollider = PhysicsCollider;
	exports.PhysicsComponent = PhysicsComponent;
	exports.PhysicsSettings = PhysicsSettings;
	exports.PhysicsSimulation = PhysicsSimulation;
	exports.PhysicsTriggerComponent = PhysicsTriggerComponent;
	exports.PhysicsUpdateList = PhysicsUpdateList;
	exports.Picker = Picker;
	exports.PixelLineData = PixelLineData;
	exports.PixelLineFilter = PixelLineFilter;
	exports.PixelLineMaterial = PixelLineMaterial;
	exports.PixelLineRenderer = PixelLineRenderer;
	exports.PixelLineSprite3D = PixelLineSprite3D;
	exports.PixelLineVertex = PixelLineVertex;
	exports.Plane = Plane;
	exports.Point2PointConstraint = Point2PointConstraint;
	exports.PointLight = PointLight;
	exports.PostProcess = PostProcess;
	exports.PostProcessEffect = PostProcessEffect;
	exports.PostProcessRenderContext = PostProcessRenderContext;
	exports.PrimitiveMesh = PrimitiveMesh;
	exports.Quaternion = Quaternion;
	exports.QuaternionKeyframe = QuaternionKeyframe;
	exports.Rand = Rand;
	exports.RandX = RandX;
	exports.Ray = Ray;
	exports.RenderContext3D = RenderContext3D;
	exports.RenderElement = RenderElement;
	exports.RenderQueue = RenderQueue;
	exports.RenderState = RenderState;
	exports.RenderTexture = RenderTexture;
	exports.RenderableSprite3D = RenderableSprite3D;
	exports.Rigidbody3D = Rigidbody3D;
	exports.RotationOverLifetime = RotationOverLifetime;
	exports.Scene3D = Scene3D;
	exports.Scene3DShaderDeclaration = Scene3DShaderDeclaration;
	exports.Scene3DUtils = Scene3DUtils;
	exports.SceneManager = SceneManager;
	exports.ScreenQuad = ScreenQuad;
	exports.ScreenTriangle = ScreenTriangle;
	exports.Script3D = Script3D;
	exports.SetRenderTargetCMD = SetRenderTargetCMD;
	exports.SetShaderDataTextureCMD = SetShaderDataTextureCMD;
	exports.Shader3D = Shader3D;
	exports.ShaderData = ShaderData;
	exports.ShaderDefine = ShaderDefine;
	exports.ShaderInit3D = ShaderInit3D;
	exports.ShaderInstance = ShaderInstance;
	exports.ShaderPass = ShaderPass;
	exports.ShaderVariable = ShaderVariable;
	exports.ShapeUtils = ShapeUtils;
	exports.ShuriKenParticle3D = ShuriKenParticle3D;
	exports.ShuriKenParticle3DShaderDeclaration = ShuriKenParticle3DShaderDeclaration;
	exports.ShurikenParticleData = ShurikenParticleData;
	exports.ShurikenParticleMaterial = ShurikenParticleMaterial;
	exports.ShurikenParticleRenderer = ShurikenParticleRenderer;
	exports.ShurikenParticleSystem = ShurikenParticleSystem;
	exports.SimpleSingletonList = SimpleSingletonList;
	exports.SingletonList = SingletonList;
	exports.Size = Size;
	exports.SizeOverLifetime = SizeOverLifetime;
	exports.SkinnedMeshRenderer = SkinnedMeshRenderer;
	exports.SkinnedMeshSprite3D = SkinnedMeshSprite3D;
	exports.SkinnedMeshSprite3DShaderDeclaration = SkinnedMeshSprite3DShaderDeclaration;
	exports.SkyBox = SkyBox;
	exports.SkyBoxMaterial = SkyBoxMaterial;
	exports.SkyDome = SkyDome;
	exports.SkyMesh = SkyMesh;
	exports.SkyProceduralMaterial = SkyProceduralMaterial;
	exports.SkyRenderer = SkyRenderer;
	exports.SphereColliderShape = SphereColliderShape;
	exports.SphereShape = SphereShape;
	exports.SpotLight = SpotLight;
	exports.Sprite3D = Sprite3D;
	exports.StartFrame = StartFrame;
	exports.StaticBatchManager = StaticBatchManager;
	exports.StaticPlaneColliderShape = StaticPlaneColliderShape;
	exports.SubMesh = SubMesh;
	exports.SubMeshDynamicBatch = SubMeshDynamicBatch;
	exports.SubMeshInstanceBatch = SubMeshInstanceBatch;
	exports.SubMeshRenderElement = SubMeshRenderElement;
	exports.SubMeshStaticBatch = SubMeshStaticBatch;
	exports.SubShader = SubShader;
	exports.SystemUtils = SystemUtils;
	exports.TextMesh = TextMesh;
	exports.TextureCube = TextureCube;
	exports.TextureGenerator = TextureGenerator;
	exports.TextureMode = TextureMode;
	exports.TextureSheetAnimation = TextureSheetAnimation;
	exports.Touch = Touch;
	exports.TrailFilter = TrailFilter;
	exports.TrailGeometry = TrailGeometry;
	exports.TrailMaterial = TrailMaterial;
	exports.TrailRenderer = TrailRenderer;
	exports.TrailSprite3D = TrailSprite3D;
	exports.Transform3D = Transform3D;
	exports.UnlitMaterial = UnlitMaterial;
	exports.Utils3D = Utils3D;
	exports.Vector2 = Vector2;
	exports.Vector3 = Vector3;
	exports.Vector3Keyframe = Vector3Keyframe;
	exports.Vector4 = Vector4;
	exports.VelocityOverLifetime = VelocityOverLifetime;
	exports.VertexBuffer3D = VertexBuffer3D;
	exports.VertexDeclaration = VertexDeclaration;
	exports.VertexElement = VertexElement;
	exports.VertexElementFormat = VertexElementFormat;
	exports.VertexMesh = VertexMesh;
	exports.VertexPositionTerrain = VertexPositionTerrain;
	exports.VertexPositionTexture0 = VertexPositionTexture0;
	exports.VertexShuriKenParticle = VertexShuriKenParticle;
	exports.VertexShurikenParticleBillboard = VertexShurikenParticleBillboard;
	exports.VertexShurikenParticleMesh = VertexShurikenParticleMesh;
	exports.VertexTrail = VertexTrail;
	exports.Viewport = Viewport;
	exports.WaterPrimaryMaterial = WaterPrimaryMaterial;

}(window.Laya = window.Laya|| {}, Laya));
