} dataIndex If not found, return undefined/null.\n */\n queryDataIndex: function (data, payload) {\n if (payload.dataIndexInside != null) {\n return payload.dataIndexInside;\n } else if (payload.dataIndex != null) {\n return echarts.util.isArray(payload.dataIndex) ? echarts.util.map(payload.dataIndex, function (value) {\n return data.indexOfRawIndex(value);\n }) : data.indexOfRawIndex(payload.dataIndex);\n } else if (payload.name != null) {\n return echarts.util.isArray(payload.name) ? echarts.util.map(payload.name, function (value) {\n return data.indexOfName(value);\n }) : data.indexOfName(payload.name);\n }\n }\n};\nexport default retrieve;","import Geometry from '../Geometry';\nimport BoundingBox from '../math/BoundingBox';\n\n/**\n * @constructor clay.geometry.Sphere\n * @extends clay.Geometry\n * @param {Object} [opt]\n * @param {number} [widthSegments]\n * @param {number} [heightSegments]\n * @param {number} [phiStart]\n * @param {number} [phiLength]\n * @param {number} [thetaStart]\n * @param {number} [thetaLength]\n * @param {number} [radius]\n */\nvar Sphere = Geometry.extend(/** @lends clay.geometry.Sphere# */ {\n dynamic: false,\n /**\n * @type {number}\n */\n widthSegments: 40,\n /**\n * @type {number}\n */\n heightSegments: 20,\n\n /**\n * @type {number}\n */\n phiStart: 0,\n /**\n * @type {number}\n */\n phiLength: Math.PI * 2,\n\n /**\n * @type {number}\n */\n thetaStart: 0,\n /**\n * @type {number}\n */\n thetaLength: Math.PI,\n\n /**\n * @type {number}\n */\n radius: 1\n\n}, function() {\n this.build();\n},\n/** @lends clay.geometry.Sphere.prototype */\n{\n /**\n * Build sphere geometry\n */\n build: function() {\n var heightSegments = this.heightSegments;\n var widthSegments = this.widthSegments;\n\n var positionAttr = this.attributes.position;\n var texcoordAttr = this.attributes.texcoord0;\n var normalAttr = this.attributes.normal;\n\n var vertexCount = (widthSegments + 1) * (heightSegments + 1);\n positionAttr.init(vertexCount);\n texcoordAttr.init(vertexCount);\n normalAttr.init(vertexCount);\n\n var IndicesCtor = vertexCount > 0xffff ? Uint32Array : Uint16Array;\n var indices = this.indices = new IndicesCtor(widthSegments * heightSegments * 6);\n\n var x, y, z,\n u, v,\n i, j;\n\n var radius = this.radius;\n var phiStart = this.phiStart;\n var phiLength = this.phiLength;\n var thetaStart = this.thetaStart;\n var thetaLength = this.thetaLength;\n var radius = this.radius;\n\n var pos = [];\n var uv = [];\n var offset = 0;\n var divider = 1 / radius;\n for (j = 0; j <= heightSegments; j ++) {\n for (i = 0; i <= widthSegments; i ++) {\n u = i / widthSegments;\n v = j / heightSegments;\n\n // X axis is inverted so texture can be mapped from left to right\n x = -radius * Math.cos(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength);\n y = radius * Math.cos(thetaStart + v * thetaLength);\n z = radius * Math.sin(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength);\n\n pos[0] = x; pos[1] = y; pos[2] = z;\n uv[0] = u; uv[1] = v;\n positionAttr.set(offset, pos);\n texcoordAttr.set(offset, uv);\n pos[0] *= divider;\n pos[1] *= divider;\n pos[2] *= divider;\n normalAttr.set(offset, pos);\n offset++;\n }\n }\n\n var i1, i2, i3, i4;\n\n var len = widthSegments + 1;\n\n var n = 0;\n for (j = 0; j < heightSegments; j ++) {\n for (i = 0; i < widthSegments; i ++) {\n i2 = j * len + i;\n i1 = (j * len + i + 1);\n i4 = (j + 1) * len + i + 1;\n i3 = (j + 1) * len + i;\n\n indices[n++] = i1;\n indices[n++] = i2;\n indices[n++] = i4;\n\n indices[n++] = i2;\n indices[n++] = i3;\n indices[n++] = i4;\n }\n }\n\n this.boundingBox = new BoundingBox();\n this.boundingBox.max.set(radius, radius, radius);\n this.boundingBox.min.set(-radius, -radius, -radius);\n }\n});\n\nexport default Sphere;\n","import Light from '../Light';\n\n/**\n * @constructor clay.light.Ambient\n * @extends clay.Light\n */\nvar AmbientLight = Light.extend({\n\n castShadow: false\n\n}, {\n\n type: 'AMBIENT_LIGHT',\n\n uniformTemplates: {\n ambientLightColor: {\n type: '3f',\n value: function(instance) {\n var color = instance.color;\n var intensity = instance.intensity;\n return [color[0]*intensity, color[1]*intensity, color[2]*intensity];\n }\n }\n }\n /**\n * @function\n * @name clone\n * @return {clay.light.Ambient}\n * @memberOf clay.light.Ambient.prototype\n */\n});\n\nexport default AmbientLight;\n","import Light from '../Light';\nimport Vector3 from '../math/Vector3';\n\n/**\n * @constructor clay.light.Directional\n * @extends clay.Light\n *\n * @example\n * var light = new clay.light.Directional({\n * intensity: 0.5,\n * color: [1.0, 0.0, 0.0]\n * });\n * light.position.set(10, 10, 10);\n * light.lookAt(clay.Vector3.ZERO);\n * scene.add(light);\n */\nvar DirectionalLight = Light.extend(/** @lends clay.light.Directional# */ {\n /**\n * @type {number}\n */\n shadowBias: 0.001,\n /**\n * @type {number}\n */\n shadowSlopeScale: 2.0,\n /**\n * Shadow cascade.\n * Use PSSM technique when it is larger than 1 and have a unique directional light in scene.\n * @type {number}\n */\n shadowCascade: 1,\n\n /**\n * Available when shadowCascade is larger than 1 and have a unique directional light in scene.\n * @type {number}\n */\n cascadeSplitLogFactor: 0.2\n}, {\n\n type: 'DIRECTIONAL_LIGHT',\n\n uniformTemplates: {\n directionalLightDirection: {\n type: '3f',\n value: function (instance) {\n instance.__dir = instance.__dir || new Vector3();\n // Direction is target to eye\n return instance.__dir.copy(instance.worldTransform.z).normalize().negate().array;\n }\n },\n directionalLightColor: {\n type: '3f',\n value: function (instance) {\n var color = instance.color;\n var intensity = instance.intensity;\n return [color[0] * intensity, color[1] * intensity, color[2] * intensity];\n }\n }\n },\n /**\n * @return {clay.light.Directional}\n * @memberOf clay.light.Directional.prototype\n */\n clone: function () {\n var light = Light.prototype.clone.call(this);\n light.shadowBias = this.shadowBias;\n light.shadowSlopeScale = this.shadowSlopeScale;\n return light;\n }\n});\n\nexport default DirectionalLight;\n","import Light from '../Light';\n\n/**\n * @constructor clay.light.Point\n * @extends clay.Light\n */\nvar PointLight = Light.extend(/** @lends clay.light.Point# */ {\n /**\n * @type {number}\n */\n range: 100,\n\n /**\n * @type {number}\n */\n castShadow: false\n}, {\n\n type: 'POINT_LIGHT',\n\n uniformTemplates: {\n pointLightPosition: {\n type: '3f',\n value: function(instance) {\n return instance.getWorldPosition().array;\n }\n },\n pointLightRange: {\n type: '1f',\n value: function(instance) {\n return instance.range;\n }\n },\n pointLightColor: {\n type: '3f',\n value: function(instance) {\n var color = instance.color;\n var intensity = instance.intensity;\n return [color[0] * intensity, color[1] * intensity, color[2] * intensity];\n }\n }\n },\n /**\n * @return {clay.light.Point}\n * @memberOf clay.light.Point.prototype\n */\n clone: function() {\n var light = Light.prototype.clone.call(this);\n light.range = this.range;\n return light;\n }\n});\n\nexport default PointLight;\n","import Light from '../Light';\nimport Vector3 from '../math/Vector3';\n\n/**\n * @constructor clay.light.Spot\n * @extends clay.Light\n */\nvar SpotLight = Light.extend(/**@lends clay.light.Spot */ {\n /**\n * @type {number}\n */\n range: 20,\n /**\n * @type {number}\n */\n umbraAngle: 30,\n /**\n * @type {number}\n */\n penumbraAngle: 45,\n /**\n * @type {number}\n */\n falloffFactor: 2.0,\n /**\n * @type {number}\n */\n shadowBias: 0.001,\n /**\n * @type {number}\n */\n shadowSlopeScale: 2.0\n}, {\n\n type: 'SPOT_LIGHT',\n\n uniformTemplates: {\n spotLightPosition: {\n type: '3f',\n value: function (instance) {\n return instance.getWorldPosition().array;\n }\n },\n spotLightRange: {\n type: '1f',\n value: function (instance) {\n return instance.range;\n }\n },\n spotLightUmbraAngleCosine: {\n type: '1f',\n value: function (instance) {\n return Math.cos(instance.umbraAngle * Math.PI / 180);\n }\n },\n spotLightPenumbraAngleCosine: {\n type: '1f',\n value: function (instance) {\n return Math.cos(instance.penumbraAngle * Math.PI / 180);\n }\n },\n spotLightFalloffFactor: {\n type: '1f',\n value: function (instance) {\n return instance.falloffFactor;\n }\n },\n spotLightDirection: {\n type: '3f',\n value: function (instance) {\n instance.__dir = instance.__dir || new Vector3();\n // Direction is target to eye\n return instance.__dir.copy(instance.worldTransform.z).negate().array;\n }\n },\n spotLightColor: {\n type: '3f',\n value: function (instance) {\n var color = instance.color;\n var intensity = instance.intensity;\n return [color[0] * intensity, color[1] * intensity, color[2] * intensity];\n }\n }\n },\n /**\n * @return {clay.light.Spot}\n * @memberOf clay.light.Spot.prototype\n */\n clone: function () {\n var light = Light.prototype.clone.call(this);\n light.range = this.range;\n light.umbraAngle = this.umbraAngle;\n light.penumbraAngle = this.penumbraAngle;\n light.falloffFactor = this.falloffFactor;\n light.shadowBias = this.shadowBias;\n light.shadowSlopeScale = this.shadowSlopeScale;\n return light;\n }\n});\n\nexport default SpotLight;\n","import vec4 from '../glmatrix/vec4';\n\n/**\n * @constructor\n * @alias clay.Vector4\n * @param {number} x\n * @param {number} y\n * @param {number} z\n * @param {number} w\n */\nvar Vector4 = function(x, y, z, w) {\n\n x = x || 0;\n y = y || 0;\n z = z || 0;\n w = w || 0;\n\n /**\n * Storage of Vector4, read and write of x, y, z, w will change the values in array\n * All methods also operate on the array instead of x, y, z, w components\n * @name array\n * @type {Float32Array}\n * @memberOf clay.Vector4#\n */\n this.array = vec4.fromValues(x, y, z, w);\n\n /**\n * Dirty flag is used by the Node to determine\n * if the matrix is updated to latest\n * @name _dirty\n * @type {boolean}\n * @memberOf clay.Vector4#\n */\n this._dirty = true;\n};\n\nVector4.prototype = {\n\n constructor: Vector4,\n\n /**\n * Add b to self\n * @param {clay.Vector4} b\n * @return {clay.Vector4}\n */\n add: function(b) {\n vec4.add(this.array, this.array, b.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Set x, y and z components\n * @param {number} x\n * @param {number} y\n * @param {number} z\n * @param {number} w\n * @return {clay.Vector4}\n */\n set: function(x, y, z, w) {\n this.array[0] = x;\n this.array[1] = y;\n this.array[2] = z;\n this.array[3] = w;\n this._dirty = true;\n return this;\n },\n\n /**\n * Set x, y, z and w components from array\n * @param {Float32Array|number[]} arr\n * @return {clay.Vector4}\n */\n setArray: function(arr) {\n this.array[0] = arr[0];\n this.array[1] = arr[1];\n this.array[2] = arr[2];\n this.array[3] = arr[3];\n\n this._dirty = true;\n return this;\n },\n\n /**\n * Clone a new Vector4\n * @return {clay.Vector4}\n */\n clone: function() {\n return new Vector4(this.x, this.y, this.z, this.w);\n },\n\n /**\n * Copy from b\n * @param {clay.Vector4} b\n * @return {clay.Vector4}\n */\n copy: function(b) {\n vec4.copy(this.array, b.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Alias for distance\n * @param {clay.Vector4} b\n * @return {number}\n */\n dist: function(b) {\n return vec4.dist(this.array, b.array);\n },\n\n /**\n * Distance between self and b\n * @param {clay.Vector4} b\n * @return {number}\n */\n distance: function(b) {\n return vec4.distance(this.array, b.array);\n },\n\n /**\n * Alias for divide\n * @param {clay.Vector4} b\n * @return {clay.Vector4}\n */\n div: function(b) {\n vec4.div(this.array, this.array, b.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Divide self by b\n * @param {clay.Vector4} b\n * @return {clay.Vector4}\n */\n divide: function(b) {\n vec4.divide(this.array, this.array, b.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Dot product of self and b\n * @param {clay.Vector4} b\n * @return {number}\n */\n dot: function(b) {\n return vec4.dot(this.array, b.array);\n },\n\n /**\n * Alias of length\n * @return {number}\n */\n len: function() {\n return vec4.len(this.array);\n },\n\n /**\n * Calculate the length\n * @return {number}\n */\n length: function() {\n return vec4.length(this.array);\n },\n /**\n * Linear interpolation between a and b\n * @param {clay.Vector4} a\n * @param {clay.Vector4} b\n * @param {number} t\n * @return {clay.Vector4}\n */\n lerp: function(a, b, t) {\n vec4.lerp(this.array, a.array, b.array, t);\n this._dirty = true;\n return this;\n },\n\n /**\n * Minimum of self and b\n * @param {clay.Vector4} b\n * @return {clay.Vector4}\n */\n min: function(b) {\n vec4.min(this.array, this.array, b.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Maximum of self and b\n * @param {clay.Vector4} b\n * @return {clay.Vector4}\n */\n max: function(b) {\n vec4.max(this.array, this.array, b.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Alias for multiply\n * @param {clay.Vector4} b\n * @return {clay.Vector4}\n */\n mul: function(b) {\n vec4.mul(this.array, this.array, b.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Mutiply self and b\n * @param {clay.Vector4} b\n * @return {clay.Vector4}\n */\n multiply: function(b) {\n vec4.multiply(this.array, this.array, b.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Negate self\n * @return {clay.Vector4}\n */\n negate: function() {\n vec4.negate(this.array, this.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Normalize self\n * @return {clay.Vector4}\n */\n normalize: function() {\n vec4.normalize(this.array, this.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Generate random x, y, z, w components with a given scale\n * @param {number} scale\n * @return {clay.Vector4}\n */\n random: function(scale) {\n vec4.random(this.array, scale);\n this._dirty = true;\n return this;\n },\n\n /**\n * Scale self\n * @param {number} scale\n * @return {clay.Vector4}\n */\n scale: function(s) {\n vec4.scale(this.array, this.array, s);\n this._dirty = true;\n return this;\n },\n /**\n * Scale b and add to self\n * @param {clay.Vector4} b\n * @param {number} scale\n * @return {clay.Vector4}\n */\n scaleAndAdd: function(b, s) {\n vec4.scaleAndAdd(this.array, this.array, b.array, s);\n this._dirty = true;\n return this;\n },\n\n /**\n * Alias for squaredDistance\n * @param {clay.Vector4} b\n * @return {number}\n */\n sqrDist: function(b) {\n return vec4.sqrDist(this.array, b.array);\n },\n\n /**\n * Squared distance between self and b\n * @param {clay.Vector4} b\n * @return {number}\n */\n squaredDistance: function(b) {\n return vec4.squaredDistance(this.array, b.array);\n },\n\n /**\n * Alias for squaredLength\n * @return {number}\n */\n sqrLen: function() {\n return vec4.sqrLen(this.array);\n },\n\n /**\n * Squared length of self\n * @return {number}\n */\n squaredLength: function() {\n return vec4.squaredLength(this.array);\n },\n\n /**\n * Alias for subtract\n * @param {clay.Vector4} b\n * @return {clay.Vector4}\n */\n sub: function(b) {\n vec4.sub(this.array, this.array, b.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Subtract b from self\n * @param {clay.Vector4} b\n * @return {clay.Vector4}\n */\n subtract: function(b) {\n vec4.subtract(this.array, this.array, b.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Transform self with a Matrix4 m\n * @param {clay.Matrix4} m\n * @return {clay.Vector4}\n */\n transformMat4: function(m) {\n vec4.transformMat4(this.array, this.array, m.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Transform self with a Quaternion q\n * @param {clay.Quaternion} q\n * @return {clay.Vector4}\n */\n transformQuat: function(q) {\n vec4.transformQuat(this.array, this.array, q.array);\n this._dirty = true;\n return this;\n },\n\n toString: function() {\n return '[' + Array.prototype.join.call(this.array, ',') + ']';\n },\n\n toArray: function () {\n return Array.prototype.slice.call(this.array);\n }\n};\n\nvar defineProperty = Object.defineProperty;\n// Getter and Setter\nif (defineProperty) {\n\n var proto = Vector4.prototype;\n /**\n * @name x\n * @type {number}\n * @memberOf clay.Vector4\n * @instance\n */\n defineProperty(proto, 'x', {\n get: function () {\n return this.array[0];\n },\n set: function (value) {\n this.array[0] = value;\n this._dirty = true;\n }\n });\n\n /**\n * @name y\n * @type {number}\n * @memberOf clay.Vector4\n * @instance\n */\n defineProperty(proto, 'y', {\n get: function () {\n return this.array[1];\n },\n set: function (value) {\n this.array[1] = value;\n this._dirty = true;\n }\n });\n\n /**\n * @name z\n * @type {number}\n * @memberOf clay.Vector4\n * @instance\n */\n defineProperty(proto, 'z', {\n get: function () {\n return this.array[2];\n },\n set: function (value) {\n this.array[2] = value;\n this._dirty = true;\n }\n });\n\n /**\n * @name w\n * @type {number}\n * @memberOf clay.Vector4\n * @instance\n */\n defineProperty(proto, 'w', {\n get: function () {\n return this.array[3];\n },\n set: function (value) {\n this.array[3] = value;\n this._dirty = true;\n }\n });\n}\n\n// Supply methods that are not in place\n\n/**\n * @param {clay.Vector4} out\n * @param {clay.Vector4} a\n * @param {clay.Vector4} b\n * @return {clay.Vector4}\n */\nVector4.add = function(out, a, b) {\n vec4.add(out.array, a.array, b.array);\n out._dirty = true;\n return out;\n};\n\n/**\n * @param {clay.Vector4} out\n * @param {number} x\n * @param {number} y\n * @param {number} z\n * @return {clay.Vector4}\n */\nVector4.set = function(out, x, y, z, w) {\n vec4.set(out.array, x, y, z, w);\n out._dirty = true;\n};\n\n/**\n * @param {clay.Vector4} out\n * @param {clay.Vector4} b\n * @return {clay.Vector4}\n */\nVector4.copy = function(out, b) {\n vec4.copy(out.array, b.array);\n out._dirty = true;\n return out;\n};\n\n/**\n * @param {clay.Vector4} a\n * @param {clay.Vector4} b\n * @return {number}\n */\nVector4.dist = function(a, b) {\n return vec4.distance(a.array, b.array);\n};\n\n/**\n * @function\n * @param {clay.Vector4} a\n * @param {clay.Vector4} b\n * @return {number}\n */\nVector4.distance = Vector4.dist;\n\n/**\n * @param {clay.Vector4} out\n * @param {clay.Vector4} a\n * @param {clay.Vector4} b\n * @return {clay.Vector4}\n */\nVector4.div = function(out, a, b) {\n vec4.divide(out.array, a.array, b.array);\n out._dirty = true;\n return out;\n};\n\n/**\n * @function\n * @param {clay.Vector4} out\n * @param {clay.Vector4} a\n * @param {clay.Vector4} b\n * @return {clay.Vector4}\n */\nVector4.divide = Vector4.div;\n\n/**\n * @param {clay.Vector4} a\n * @param {clay.Vector4} b\n * @return {number}\n */\nVector4.dot = function(a, b) {\n return vec4.dot(a.array, b.array);\n};\n\n/**\n * @param {clay.Vector4} a\n * @return {number}\n */\nVector4.len = function(b) {\n return vec4.length(b.array);\n};\n\n// Vector4.length = Vector4.len;\n\n/**\n * @param {clay.Vector4} out\n * @param {clay.Vector4} a\n * @param {clay.Vector4} b\n * @param {number} t\n * @return {clay.Vector4}\n */\nVector4.lerp = function(out, a, b, t) {\n vec4.lerp(out.array, a.array, b.array, t);\n out._dirty = true;\n return out;\n};\n\n/**\n * @param {clay.Vector4} out\n * @param {clay.Vector4} a\n * @param {clay.Vector4} b\n * @return {clay.Vector4}\n */\nVector4.min = function(out, a, b) {\n vec4.min(out.array, a.array, b.array);\n out._dirty = true;\n return out;\n};\n\n/**\n * @param {clay.Vector4} out\n * @param {clay.Vector4} a\n * @param {clay.Vector4} b\n * @return {clay.Vector4}\n */\nVector4.max = function(out, a, b) {\n vec4.max(out.array, a.array, b.array);\n out._dirty = true;\n return out;\n};\n\n/**\n * @param {clay.Vector4} out\n * @param {clay.Vector4} a\n * @param {clay.Vector4} b\n * @return {clay.Vector4}\n */\nVector4.mul = function(out, a, b) {\n vec4.multiply(out.array, a.array, b.array);\n out._dirty = true;\n return out;\n};\n\n/**\n * @function\n * @param {clay.Vector4} out\n * @param {clay.Vector4} a\n * @param {clay.Vector4} b\n * @return {clay.Vector4}\n */\nVector4.multiply = Vector4.mul;\n\n/**\n * @param {clay.Vector4} out\n * @param {clay.Vector4} a\n * @return {clay.Vector4}\n */\nVector4.negate = function(out, a) {\n vec4.negate(out.array, a.array);\n out._dirty = true;\n return out;\n};\n\n/**\n * @param {clay.Vector4} out\n * @param {clay.Vector4} a\n * @return {clay.Vector4}\n */\nVector4.normalize = function(out, a) {\n vec4.normalize(out.array, a.array);\n out._dirty = true;\n return out;\n};\n\n/**\n * @param {clay.Vector4} out\n * @param {number} scale\n * @return {clay.Vector4}\n */\nVector4.random = function(out, scale) {\n vec4.random(out.array, scale);\n out._dirty = true;\n return out;\n};\n\n/**\n * @param {clay.Vector4} out\n * @param {clay.Vector4} a\n * @param {number} scale\n * @return {clay.Vector4}\n */\nVector4.scale = function(out, a, scale) {\n vec4.scale(out.array, a.array, scale);\n out._dirty = true;\n return out;\n};\n\n/**\n * @param {clay.Vector4} out\n * @param {clay.Vector4} a\n * @param {clay.Vector4} b\n * @param {number} scale\n * @return {clay.Vector4}\n */\nVector4.scaleAndAdd = function(out, a, b, scale) {\n vec4.scaleAndAdd(out.array, a.array, b.array, scale);\n out._dirty = true;\n return out;\n};\n\n/**\n * @param {clay.Vector4} a\n * @param {clay.Vector4} b\n * @return {number}\n */\nVector4.sqrDist = function(a, b) {\n return vec4.sqrDist(a.array, b.array);\n};\n\n/**\n * @function\n * @param {clay.Vector4} a\n * @param {clay.Vector4} b\n * @return {number}\n */\nVector4.squaredDistance = Vector4.sqrDist;\n\n/**\n * @param {clay.Vector4} a\n * @return {number}\n */\nVector4.sqrLen = function(a) {\n return vec4.sqrLen(a.array);\n};\n/**\n * @function\n * @param {clay.Vector4} a\n * @return {number}\n */\nVector4.squaredLength = Vector4.sqrLen;\n\n/**\n * @param {clay.Vector4} out\n * @param {clay.Vector4} a\n * @param {clay.Vector4} b\n * @return {clay.Vector4}\n */\nVector4.sub = function(out, a, b) {\n vec4.subtract(out.array, a.array, b.array);\n out._dirty = true;\n return out;\n};\n/**\n * @function\n * @param {clay.Vector4} out\n * @param {clay.Vector4} a\n * @param {clay.Vector4} b\n * @return {clay.Vector4}\n */\nVector4.subtract = Vector4.sub;\n\n/**\n * @param {clay.Vector4} out\n * @param {clay.Vector4} a\n * @param {clay.Matrix4} m\n * @return {clay.Vector4}\n */\nVector4.transformMat4 = function(out, a, m) {\n vec4.transformMat4(out.array, a.array, m.array);\n out._dirty = true;\n return out;\n};\n\n/**\n * @param {clay.Vector4} out\n * @param {clay.Vector4} a\n * @param {clay.Quaternion} q\n * @return {clay.Vector4}\n */\nVector4.transformQuat = function(out, a, q) {\n vec4.transformQuat(out.array, a.array, q.array);\n out._dirty = true;\n return out;\n};\n\nexport default Vector4;\n","\n\n/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\n * Redistributions of source code must retain the above copyright notice, this\n list of conditions and the following disclaimer.\n * Redistributions in binary form must reproduce the above copyright notice,\n this list of conditions and the following disclaimer in the documentation\n and/or other materials provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR\nANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\nANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */\n\nimport { GLMAT_ARRAY_TYPE } from './common';\n\n/**\n * @class 2x2 Matrix\n * @name mat2\n */\n\nvar mat2 = {};\n\n/**\n * Creates a new identity mat2\n *\n * @returns {mat2} a new 2x2 matrix\n */\nmat2.create = function() {\n var out = new GLMAT_ARRAY_TYPE(4);\n out[0] = 1;\n out[1] = 0;\n out[2] = 0;\n out[3] = 1;\n return out;\n};\n\n/**\n * Creates a new mat2 initialized with values from an existing matrix\n *\n * @param {mat2} a matrix to clone\n * @returns {mat2} a new 2x2 matrix\n */\nmat2.clone = function(a) {\n var out = new GLMAT_ARRAY_TYPE(4);\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n out[3] = a[3];\n return out;\n};\n\n/**\n * Copy the values from one mat2 to another\n *\n * @param {mat2} out the receiving matrix\n * @param {mat2} a the source matrix\n * @returns {mat2} out\n */\nmat2.copy = function(out, a) {\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n out[3] = a[3];\n return out;\n};\n\n/**\n * Set a mat2 to the identity matrix\n *\n * @param {mat2} out the receiving matrix\n * @returns {mat2} out\n */\nmat2.identity = function(out) {\n out[0] = 1;\n out[1] = 0;\n out[2] = 0;\n out[3] = 1;\n return out;\n};\n\n/**\n * Transpose the values of a mat2\n *\n * @param {mat2} out the receiving matrix\n * @param {mat2} a the source matrix\n * @returns {mat2} out\n */\nmat2.transpose = function(out, a) {\n // If we are transposing ourselves we can skip a few steps but have to cache some values\n if (out === a) {\n var a1 = a[1];\n out[1] = a[2];\n out[2] = a1;\n } else {\n out[0] = a[0];\n out[1] = a[2];\n out[2] = a[1];\n out[3] = a[3];\n }\n\n return out;\n};\n\n/**\n * Inverts a mat2\n *\n * @param {mat2} out the receiving matrix\n * @param {mat2} a the source matrix\n * @returns {mat2} out\n */\nmat2.invert = function(out, a) {\n var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3],\n\n // Calculate the determinant\n det = a0 * a3 - a2 * a1;\n\n if (!det) {\n return null;\n }\n det = 1.0 / det;\n\n out[0] = a3 * det;\n out[1] = -a1 * det;\n out[2] = -a2 * det;\n out[3] = a0 * det;\n\n return out;\n};\n\n/**\n * Calculates the adjugate of a mat2\n *\n * @param {mat2} out the receiving matrix\n * @param {mat2} a the source matrix\n * @returns {mat2} out\n */\nmat2.adjoint = function(out, a) {\n // Caching this value is nessecary if out == a\n var a0 = a[0];\n out[0] = a[3];\n out[1] = -a[1];\n out[2] = -a[2];\n out[3] = a0;\n\n return out;\n};\n\n/**\n * Calculates the determinant of a mat2\n *\n * @param {mat2} a the source matrix\n * @returns {Number} determinant of a\n */\nmat2.determinant = function (a) {\n return a[0] * a[3] - a[2] * a[1];\n};\n\n/**\n * Multiplies two mat2's\n *\n * @param {mat2} out the receiving matrix\n * @param {mat2} a the first operand\n * @param {mat2} b the second operand\n * @returns {mat2} out\n */\nmat2.multiply = function (out, a, b) {\n var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3];\n var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3];\n out[0] = a0 * b0 + a2 * b1;\n out[1] = a1 * b0 + a3 * b1;\n out[2] = a0 * b2 + a2 * b3;\n out[3] = a1 * b2 + a3 * b3;\n return out;\n};\n\n/**\n * Alias for {@link mat2.multiply}\n * @function\n */\nmat2.mul = mat2.multiply;\n\n/**\n * Rotates a mat2 by the given angle\n *\n * @param {mat2} out the receiving matrix\n * @param {mat2} a the matrix to rotate\n * @param {Number} rad the angle to rotate the matrix by\n * @returns {mat2} out\n */\nmat2.rotate = function (out, a, rad) {\n var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3],\n s = Math.sin(rad),\n c = Math.cos(rad);\n out[0] = a0 * c + a2 * s;\n out[1] = a1 * c + a3 * s;\n out[2] = a0 * -s + a2 * c;\n out[3] = a1 * -s + a3 * c;\n return out;\n};\n\n/**\n * Scales the mat2 by the dimensions in the given vec2\n *\n * @param {mat2} out the receiving matrix\n * @param {mat2} a the matrix to rotate\n * @param {vec2} v the vec2 to scale the matrix by\n * @returns {mat2} out\n **/\nmat2.scale = function(out, a, v) {\n var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3],\n v0 = v[0], v1 = v[1];\n out[0] = a0 * v0;\n out[1] = a1 * v0;\n out[2] = a2 * v1;\n out[3] = a3 * v1;\n return out;\n};\n\n/**\n * Returns Frobenius norm of a mat2\n *\n * @param {mat2} a the matrix to calculate Frobenius norm of\n * @returns {Number} Frobenius norm\n */\nmat2.frob = function (a) {\n return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2)))\n};\n\n/**\n * Returns L, D and U matrices (Lower triangular, Diagonal and Upper triangular) by factorizing the input matrix\n * @param {mat2} L the lower triangular matrix\n * @param {mat2} D the diagonal matrix\n * @param {mat2} U the upper triangular matrix\n * @param {mat2} a the input matrix to factorize\n */\n\nmat2.LDU = function (L, D, U, a) {\n L[2] = a[2]/a[0];\n U[0] = a[0];\n U[1] = a[1];\n U[3] = a[3] - L[2] * U[1];\n return [L, D, U];\n};\n\n\nexport default mat2;","import mat2 from '../glmatrix/mat2';\n\n/**\n * @constructor\n * @alias clay.Matrix2\n */\nvar Matrix2 = function() {\n\n /**\n * Storage of Matrix2\n * @name array\n * @type {Float32Array}\n * @memberOf clay.Matrix2#\n */\n this.array = mat2.create();\n\n /**\n * @name _dirty\n * @type {boolean}\n * @memberOf clay.Matrix2#\n */\n this._dirty = true;\n};\n\nMatrix2.prototype = {\n\n constructor: Matrix2,\n\n /**\n * Set components from array\n * @param {Float32Array|number[]} arr\n */\n setArray: function (arr) {\n for (var i = 0; i < this.array.length; i++) {\n this.array[i] = arr[i];\n }\n this._dirty = true;\n return this;\n },\n /**\n * Clone a new Matrix2\n * @return {clay.Matrix2}\n */\n clone: function() {\n return (new Matrix2()).copy(this);\n },\n\n /**\n * Copy from b\n * @param {clay.Matrix2} b\n * @return {clay.Matrix2}\n */\n copy: function(b) {\n mat2.copy(this.array, b.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Calculate the adjugate of self, in-place\n * @return {clay.Matrix2}\n */\n adjoint: function() {\n mat2.adjoint(this.array, this.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Calculate matrix determinant\n * @return {number}\n */\n determinant: function() {\n return mat2.determinant(this.array);\n },\n\n /**\n * Set to a identity matrix\n * @return {clay.Matrix2}\n */\n identity: function() {\n mat2.identity(this.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Invert self\n * @return {clay.Matrix2}\n */\n invert: function() {\n mat2.invert(this.array, this.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Alias for mutiply\n * @param {clay.Matrix2} b\n * @return {clay.Matrix2}\n */\n mul: function(b) {\n mat2.mul(this.array, this.array, b.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Alias for multiplyLeft\n * @param {clay.Matrix2} a\n * @return {clay.Matrix2}\n */\n mulLeft: function(a) {\n mat2.mul(this.array, a.array, this.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Multiply self and b\n * @param {clay.Matrix2} b\n * @return {clay.Matrix2}\n */\n multiply: function(b) {\n mat2.multiply(this.array, this.array, b.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Multiply a and self, a is on the left\n * @param {clay.Matrix2} a\n * @return {clay.Matrix2}\n */\n multiplyLeft: function(a) {\n mat2.multiply(this.array, a.array, this.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Rotate self by a given radian\n * @param {number} rad\n * @return {clay.Matrix2}\n */\n rotate: function(rad) {\n mat2.rotate(this.array, this.array, rad);\n this._dirty = true;\n return this;\n },\n\n /**\n * Scale self by s\n * @param {clay.Vector2} s\n * @return {clay.Matrix2}\n */\n scale: function(v) {\n mat2.scale(this.array, this.array, v.array);\n this._dirty = true;\n return this;\n },\n /**\n * Transpose self, in-place.\n * @return {clay.Matrix2}\n */\n transpose: function() {\n mat2.transpose(this.array, this.array);\n this._dirty = true;\n return this;\n },\n\n toString: function() {\n return '[' + Array.prototype.join.call(this.array, ',') + ']';\n },\n\n toArray: function () {\n return Array.prototype.slice.call(this.array);\n }\n};\n\n/**\n * @param {Matrix2} out\n * @param {Matrix2} a\n * @return {Matrix2}\n */\nMatrix2.adjoint = function(out, a) {\n mat2.adjoint(out.array, a.array);\n out._dirty = true;\n return out;\n};\n\n/**\n * @param {clay.Matrix2} out\n * @param {clay.Matrix2} a\n * @return {clay.Matrix2}\n */\nMatrix2.copy = function(out, a) {\n mat2.copy(out.array, a.array);\n out._dirty = true;\n return out;\n};\n\n/**\n * @param {clay.Matrix2} a\n * @return {number}\n */\nMatrix2.determinant = function(a) {\n return mat2.determinant(a.array);\n};\n\n/**\n * @param {clay.Matrix2} out\n * @return {clay.Matrix2}\n */\nMatrix2.identity = function(out) {\n mat2.identity(out.array);\n out._dirty = true;\n return out;\n};\n\n/**\n * @param {clay.Matrix2} out\n * @param {clay.Matrix2} a\n * @return {clay.Matrix2}\n */\nMatrix2.invert = function(out, a) {\n mat2.invert(out.array, a.array);\n out._dirty = true;\n return out;\n};\n\n/**\n * @param {clay.Matrix2} out\n * @param {clay.Matrix2} a\n * @param {clay.Matrix2} b\n * @return {clay.Matrix2}\n */\nMatrix2.mul = function(out, a, b) {\n mat2.mul(out.array, a.array, b.array);\n out._dirty = true;\n return out;\n};\n\n/**\n * @function\n * @param {clay.Matrix2} out\n * @param {clay.Matrix2} a\n * @param {clay.Matrix2} b\n * @return {clay.Matrix2}\n */\nMatrix2.multiply = Matrix2.mul;\n\n/**\n * @param {clay.Matrix2} out\n * @param {clay.Matrix2} a\n * @param {number} rad\n * @return {clay.Matrix2}\n */\nMatrix2.rotate = function(out, a, rad) {\n mat2.rotate(out.array, a.array, rad);\n out._dirty = true;\n return out;\n};\n\n/**\n * @param {clay.Matrix2} out\n * @param {clay.Matrix2} a\n * @param {clay.Vector2} v\n * @return {clay.Matrix2}\n */\nMatrix2.scale = function(out, a, v) {\n mat2.scale(out.array, a.array, v.array);\n out._dirty = true;\n return out;\n};\n/**\n * @param {Matrix2} out\n * @param {Matrix2} a\n * @return {Matrix2}\n */\nMatrix2.transpose = function(out, a) {\n mat2.transpose(out.array, a.array);\n out._dirty = true;\n return out;\n};\n\nexport default Matrix2;\n","\n/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\n * Redistributions of source code must retain the above copyright notice, this\n list of conditions and the following disclaimer.\n * Redistributions in binary form must reproduce the above copyright notice,\n this list of conditions and the following disclaimer in the documentation\n and/or other materials provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR\nANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\nANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */\n\nimport { GLMAT_ARRAY_TYPE } from './common';\n\n/**\n * @class 2x3 Matrix\n * @name mat2d\n *\n * @description\n * A mat2d contains six elements defined as:\n * \n * [a, c, tx,\n * b, d, ty]\n *
\n * This is a short form for the 3x3 matrix:\n * \n * [a, c, tx,\n * b, d, ty,\n * 0, 0, 1]\n *
\n * The last row is ignored so the array is shorter and operations are faster.\n */\n\nvar mat2d = {};\n\n/**\n * Creates a new identity mat2d\n *\n * @returns {mat2d} a new 2x3 matrix\n */\nmat2d.create = function() {\n var out = new GLMAT_ARRAY_TYPE(6);\n out[0] = 1;\n out[1] = 0;\n out[2] = 0;\n out[3] = 1;\n out[4] = 0;\n out[5] = 0;\n return out;\n};\n\n/**\n * Creates a new mat2d initialized with values from an existing matrix\n *\n * @param {mat2d} a matrix to clone\n * @returns {mat2d} a new 2x3 matrix\n */\nmat2d.clone = function(a) {\n var out = new GLMAT_ARRAY_TYPE(6);\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n out[3] = a[3];\n out[4] = a[4];\n out[5] = a[5];\n return out;\n};\n\n/**\n * Copy the values from one mat2d to another\n *\n * @param {mat2d} out the receiving matrix\n * @param {mat2d} a the source matrix\n * @returns {mat2d} out\n */\nmat2d.copy = function(out, a) {\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n out[3] = a[3];\n out[4] = a[4];\n out[5] = a[5];\n return out;\n};\n\n/**\n * Set a mat2d to the identity matrix\n *\n * @param {mat2d} out the receiving matrix\n * @returns {mat2d} out\n */\nmat2d.identity = function(out) {\n out[0] = 1;\n out[1] = 0;\n out[2] = 0;\n out[3] = 1;\n out[4] = 0;\n out[5] = 0;\n return out;\n};\n\n/**\n * Inverts a mat2d\n *\n * @param {mat2d} out the receiving matrix\n * @param {mat2d} a the source matrix\n * @returns {mat2d} out\n */\nmat2d.invert = function(out, a) {\n var aa = a[0], ab = a[1], ac = a[2], ad = a[3],\n atx = a[4], aty = a[5];\n\n var det = aa * ad - ab * ac;\n if(!det){\n return null;\n }\n det = 1.0 / det;\n\n out[0] = ad * det;\n out[1] = -ab * det;\n out[2] = -ac * det;\n out[3] = aa * det;\n out[4] = (ac * aty - ad * atx) * det;\n out[5] = (ab * atx - aa * aty) * det;\n return out;\n};\n\n/**\n * Calculates the determinant of a mat2d\n *\n * @param {mat2d} a the source matrix\n * @returns {Number} determinant of a\n */\nmat2d.determinant = function (a) {\n return a[0] * a[3] - a[1] * a[2];\n};\n\n/**\n * Multiplies two mat2d's\n *\n * @param {mat2d} out the receiving matrix\n * @param {mat2d} a the first operand\n * @param {mat2d} b the second operand\n * @returns {mat2d} out\n */\nmat2d.multiply = function (out, a, b) {\n var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5],\n b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3], b4 = b[4], b5 = b[5];\n out[0] = a0 * b0 + a2 * b1;\n out[1] = a1 * b0 + a3 * b1;\n out[2] = a0 * b2 + a2 * b3;\n out[3] = a1 * b2 + a3 * b3;\n out[4] = a0 * b4 + a2 * b5 + a4;\n out[5] = a1 * b4 + a3 * b5 + a5;\n return out;\n};\n\n/**\n * Alias for {@link mat2d.multiply}\n * @function\n */\nmat2d.mul = mat2d.multiply;\n\n\n/**\n * Rotates a mat2d by the given angle\n *\n * @param {mat2d} out the receiving matrix\n * @param {mat2d} a the matrix to rotate\n * @param {Number} rad the angle to rotate the matrix by\n * @returns {mat2d} out\n */\nmat2d.rotate = function (out, a, rad) {\n var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5],\n s = Math.sin(rad),\n c = Math.cos(rad);\n out[0] = a0 * c + a2 * s;\n out[1] = a1 * c + a3 * s;\n out[2] = a0 * -s + a2 * c;\n out[3] = a1 * -s + a3 * c;\n out[4] = a4;\n out[5] = a5;\n return out;\n};\n\n/**\n * Scales the mat2d by the dimensions in the given vec2\n *\n * @param {mat2d} out the receiving matrix\n * @param {mat2d} a the matrix to translate\n * @param {vec2} v the vec2 to scale the matrix by\n * @returns {mat2d} out\n **/\nmat2d.scale = function(out, a, v) {\n var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5],\n v0 = v[0], v1 = v[1];\n out[0] = a0 * v0;\n out[1] = a1 * v0;\n out[2] = a2 * v1;\n out[3] = a3 * v1;\n out[4] = a4;\n out[5] = a5;\n return out;\n};\n\n/**\n * Translates the mat2d by the dimensions in the given vec2\n *\n * @param {mat2d} out the receiving matrix\n * @param {mat2d} a the matrix to translate\n * @param {vec2} v the vec2 to translate the matrix by\n * @returns {mat2d} out\n **/\nmat2d.translate = function(out, a, v) {\n var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5],\n v0 = v[0], v1 = v[1];\n out[0] = a0;\n out[1] = a1;\n out[2] = a2;\n out[3] = a3;\n out[4] = a0 * v0 + a2 * v1 + a4;\n out[5] = a1 * v0 + a3 * v1 + a5;\n return out;\n};\n\n/**\n * Returns Frobenius norm of a mat2d\n *\n * @param {mat2d} a the matrix to calculate Frobenius norm of\n * @returns {Number} Frobenius norm\n */\nmat2d.frob = function (a) {\n return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + 1))\n};\n\n\nexport default mat2d;","import mat2d from '../glmatrix/mat2d';\n\n/**\n * @constructor\n * @alias clay.Matrix2d\n */\nvar Matrix2d = function() {\n /**\n * Storage of Matrix2d\n * @name array\n * @type {Float32Array}\n * @memberOf clay.Matrix2d#\n */\n this.array = mat2d.create();\n\n /**\n * @name _dirty\n * @type {boolean}\n * @memberOf clay.Matrix2d#\n */\n this._dirty = true;\n};\n\nMatrix2d.prototype = {\n\n constructor: Matrix2d,\n\n /**\n * Set components from array\n * @param {Float32Array|number[]} arr\n */\n setArray: function (arr) {\n for (var i = 0; i < this.array.length; i++) {\n this.array[i] = arr[i];\n }\n this._dirty = true;\n return this;\n },\n /**\n * Clone a new Matrix2d\n * @return {clay.Matrix2d}\n */\n clone: function() {\n return (new Matrix2d()).copy(this);\n },\n\n /**\n * Copy from b\n * @param {clay.Matrix2d} b\n * @return {clay.Matrix2d}\n */\n copy: function(b) {\n mat2d.copy(this.array, b.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Calculate matrix determinant\n * @return {number}\n */\n determinant: function() {\n return mat2d.determinant(this.array);\n },\n\n /**\n * Set to a identity matrix\n * @return {clay.Matrix2d}\n */\n identity: function() {\n mat2d.identity(this.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Invert self\n * @return {clay.Matrix2d}\n */\n invert: function() {\n mat2d.invert(this.array, this.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Alias for mutiply\n * @param {clay.Matrix2d} b\n * @return {clay.Matrix2d}\n */\n mul: function(b) {\n mat2d.mul(this.array, this.array, b.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Alias for multiplyLeft\n * @param {clay.Matrix2d} a\n * @return {clay.Matrix2d}\n */\n mulLeft: function(b) {\n mat2d.mul(this.array, b.array, this.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Multiply self and b\n * @param {clay.Matrix2d} b\n * @return {clay.Matrix2d}\n */\n multiply: function(b) {\n mat2d.multiply(this.array, this.array, b.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Multiply a and self, a is on the left\n * @param {clay.Matrix2d} a\n * @return {clay.Matrix2d}\n */\n multiplyLeft: function(b) {\n mat2d.multiply(this.array, b.array, this.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Rotate self by a given radian\n * @param {number} rad\n * @return {clay.Matrix2d}\n */\n rotate: function(rad) {\n mat2d.rotate(this.array, this.array, rad);\n this._dirty = true;\n return this;\n },\n\n /**\n * Scale self by s\n * @param {clay.Vector2} s\n * @return {clay.Matrix2d}\n */\n scale: function(s) {\n mat2d.scale(this.array, this.array, s.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Translate self by v\n * @param {clay.Vector2} v\n * @return {clay.Matrix2d}\n */\n translate: function(v) {\n mat2d.translate(this.array, this.array, v.array);\n this._dirty = true;\n return this;\n },\n\n toString: function() {\n return '[' + Array.prototype.join.call(this.array, ',') + ']';\n },\n\n toArray: function () {\n return Array.prototype.slice.call(this.array);\n }\n};\n\n/**\n * @param {clay.Matrix2d} out\n * @param {clay.Matrix2d} a\n * @return {clay.Matrix2d}\n */\nMatrix2d.copy = function(out, a) {\n mat2d.copy(out.array, a.array);\n out._dirty = true;\n return out;\n};\n\n/**\n * @param {clay.Matrix2d} a\n * @return {number}\n */\nMatrix2d.determinant = function(a) {\n return mat2d.determinant(a.array);\n};\n\n/**\n * @param {clay.Matrix2d} out\n * @return {clay.Matrix2d}\n */\nMatrix2d.identity = function(out) {\n mat2d.identity(out.array);\n out._dirty = true;\n return out;\n};\n\n/**\n * @param {clay.Matrix2d} out\n * @param {clay.Matrix2d} a\n * @return {clay.Matrix2d}\n */\nMatrix2d.invert = function(out, a) {\n mat2d.invert(out.array, a.array);\n out._dirty = true;\n return out;\n};\n\n/**\n * @param {clay.Matrix2d} out\n * @param {clay.Matrix2d} a\n * @param {clay.Matrix2d} b\n * @return {clay.Matrix2d}\n */\nMatrix2d.mul = function(out, a, b) {\n mat2d.mul(out.array, a.array, b.array);\n out._dirty = true;\n return out;\n};\n\n/**\n * @function\n * @param {clay.Matrix2d} out\n * @param {clay.Matrix2d} a\n * @param {clay.Matrix2d} b\n * @return {clay.Matrix2d}\n */\nMatrix2d.multiply = Matrix2d.mul;\n\n/**\n * @param {clay.Matrix2d} out\n * @param {clay.Matrix2d} a\n * @param {number} rad\n * @return {clay.Matrix2d}\n */\nMatrix2d.rotate = function(out, a, rad) {\n mat2d.rotate(out.array, a.array, rad);\n out._dirty = true;\n return out;\n};\n\n/**\n * @param {clay.Matrix2d} out\n * @param {clay.Matrix2d} a\n * @param {clay.Vector2} v\n * @return {clay.Matrix2d}\n */\nMatrix2d.scale = function(out, a, v) {\n mat2d.scale(out.array, a.array, v.array);\n out._dirty = true;\n return out;\n};\n\n/**\n * @param {clay.Matrix2d} out\n * @param {clay.Matrix2d} a\n * @param {clay.Vector2} v\n * @return {clay.Matrix2d}\n */\nMatrix2d.translate = function(out, a, v) {\n mat2d.translate(out.array, a.array, v.array);\n out._dirty = true;\n return out;\n};\n\nexport default Matrix2d;\n","import mat3 from '../glmatrix/mat3';\n\n/**\n * @constructor\n * @alias clay.Matrix3\n */\nvar Matrix3 = function () {\n\n /**\n * Storage of Matrix3\n * @name array\n * @type {Float32Array}\n * @memberOf clay.Matrix3#\n */\n this.array = mat3.create();\n\n /**\n * @name _dirty\n * @type {boolean}\n * @memberOf clay.Matrix3#\n */\n this._dirty = true;\n};\n\nMatrix3.prototype = {\n\n constructor: Matrix3,\n\n /**\n * Set components from array\n * @param {Float32Array|number[]} arr\n */\n setArray: function (arr) {\n for (var i = 0; i < this.array.length; i++) {\n this.array[i] = arr[i];\n }\n this._dirty = true;\n return this;\n },\n /**\n * Calculate the adjugate of self, in-place\n * @return {clay.Matrix3}\n */\n adjoint: function () {\n mat3.adjoint(this.array, this.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Clone a new Matrix3\n * @return {clay.Matrix3}\n */\n clone: function () {\n return (new Matrix3()).copy(this);\n },\n\n /**\n * Copy from b\n * @param {clay.Matrix3} b\n * @return {clay.Matrix3}\n */\n copy: function (b) {\n mat3.copy(this.array, b.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Calculate matrix determinant\n * @return {number}\n */\n determinant: function () {\n return mat3.determinant(this.array);\n },\n\n /**\n * Copy the values from Matrix2d a\n * @param {clay.Matrix2d} a\n * @return {clay.Matrix3}\n */\n fromMat2d: function (a) {\n mat3.fromMat2d(this.array, a.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Copies the upper-left 3x3 values of Matrix4\n * @param {clay.Matrix4} a\n * @return {clay.Matrix3}\n */\n fromMat4: function (a) {\n mat3.fromMat4(this.array, a.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Calculates a rotation matrix from the given quaternion\n * @param {clay.Quaternion} q\n * @return {clay.Matrix3}\n */\n fromQuat: function (q) {\n mat3.fromQuat(this.array, q.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Set to a identity matrix\n * @return {clay.Matrix3}\n */\n identity: function () {\n mat3.identity(this.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Invert self\n * @return {clay.Matrix3}\n */\n invert: function () {\n mat3.invert(this.array, this.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Alias for mutiply\n * @param {clay.Matrix3} b\n * @return {clay.Matrix3}\n */\n mul: function (b) {\n mat3.mul(this.array, this.array, b.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Alias for multiplyLeft\n * @param {clay.Matrix3} a\n * @return {clay.Matrix3}\n */\n mulLeft: function (a) {\n mat3.mul(this.array, a.array, this.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Multiply self and b\n * @param {clay.Matrix3} b\n * @return {clay.Matrix3}\n */\n multiply: function (b) {\n mat3.multiply(this.array, this.array, b.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Multiply a and self, a is on the left\n * @param {clay.Matrix3} a\n * @return {clay.Matrix3}\n */\n multiplyLeft: function (a) {\n mat3.multiply(this.array, a.array, this.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Rotate self by a given radian\n * @param {number} rad\n * @return {clay.Matrix3}\n */\n rotate: function (rad) {\n mat3.rotate(this.array, this.array, rad);\n this._dirty = true;\n return this;\n },\n\n /**\n * Scale self by s\n * @param {clay.Vector2} s\n * @return {clay.Matrix3}\n */\n scale: function (v) {\n mat3.scale(this.array, this.array, v.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Translate self by v\n * @param {clay.Vector2} v\n * @return {clay.Matrix3}\n */\n translate: function (v) {\n mat3.translate(this.array, this.array, v.array);\n this._dirty = true;\n return this;\n },\n /**\n * Calculates a 3x3 normal matrix (transpose inverse) from the 4x4 matrix\n * @param {clay.Matrix4} a\n */\n normalFromMat4: function (a) {\n mat3.normalFromMat4(this.array, a.array);\n this._dirty = true;\n return this;\n },\n\n /**\n * Transpose self, in-place.\n * @return {clay.Matrix2}\n */\n transpose: function () {\n mat3.transpose(this.array, this.array);\n this._dirty = true;\n return this;\n },\n\n toString: function () {\n return '[' + Array.prototype.join.call(this.array, ',') + ']';\n },\n\n toArray: function () {\n return Array.prototype.slice.call(this.array);\n }\n};\n/**\n * @param {clay.Matrix3} out\n * @param {clay.Matrix3} a\n * @return {clay.Matrix3}\n */\nMatrix3.adjoint = function (out, a) {\n mat3.adjoint(out.array, a.array);\n out._dirty = true;\n return out;\n};\n\n/**\n * @param {clay.Matrix3} out\n * @param {clay.Matrix3} a\n * @return {clay.Matrix3}\n */\nMatrix3.copy = function (out, a) {\n mat3.copy(out.array, a.array);\n out._dirty = true;\n return out;\n};\n\n/**\n * @param {clay.Matrix3} a\n * @return {number}\n */\nMatrix3.determinant = function (a) {\n return mat3.determinant(a.array);\n};\n\n/**\n * @param {clay.Matrix3} out\n * @return {clay.Matrix3}\n */\nMatrix3.identity = function (out) {\n mat3.identity(out.array);\n out._dirty = true;\n return out;\n};\n\n/**\n * @param {clay.Matrix3} out\n * @param {clay.Matrix3} a\n * @return {clay.Matrix3}\n */\nMatrix3.invert = function (out, a) {\n mat3.invert(out.array, a.array);\n return out;\n};\n\n/**\n * @param {clay.Matrix3} out\n * @param {clay.Matrix3} a\n * @param {clay.Matrix3} b\n * @return {clay.Matrix3}\n */\nMatrix3.mul = function (out, a, b) {\n mat3.mul(out.array, a.array, b.array);\n out._dirty = true;\n return out;\n};\n\n/**\n * @function\n * @param {clay.Matrix3} out\n * @param {clay.Matrix3} a\n * @param {clay.Matrix3} b\n * @return {clay.Matrix3}\n */\nMatrix3.multiply = Matrix3.mul;\n\n/**\n * @param {clay.Matrix3} out\n * @param {clay.Matrix2d} a\n * @return {clay.Matrix3}\n */\nMatrix3.fromMat2d = function (out, a) {\n mat3.fromMat2d(out.array, a.array);\n out._dirty = true;\n return out;\n};\n\n/**\n * @param {clay.Matrix3} out\n * @param {clay.Matrix4} a\n * @return {clay.Matrix3}\n */\nMatrix3.fromMat4 = function (out, a) {\n mat3.fromMat4(out.array, a.array);\n out._dirty = true;\n return out;\n};\n\n/**\n * @param {clay.Matrix3} out\n * @param {clay.Quaternion} a\n * @return {clay.Matrix3}\n */\nMatrix3.fromQuat = function (out, q) {\n mat3.fromQuat(out.array, q.array);\n out._dirty = true;\n return out;\n};\n\n/**\n * @param {clay.Matrix3} out\n * @param {clay.Matrix4} a\n * @return {clay.Matrix3}\n */\nMatrix3.normalFromMat4 = function (out, a) {\n mat3.normalFromMat4(out.array, a.array);\n out._dirty = true;\n return out;\n};\n\n/**\n * @param {clay.Matrix3} out\n * @param {clay.Matrix3} a\n * @param {number} rad\n * @return {clay.Matrix3}\n */\nMatrix3.rotate = function (out, a, rad) {\n mat3.rotate(out.array, a.array, rad);\n out._dirty = true;\n return out;\n};\n\n/**\n * @param {clay.Matrix3} out\n * @param {clay.Matrix3} a\n * @param {clay.Vector2} v\n * @return {clay.Matrix3}\n */\nMatrix3.scale = function (out, a, v) {\n mat3.scale(out.array, a.array, v.array);\n out._dirty = true;\n return out;\n};\n\n/**\n * @param {clay.Matrix3} out\n * @param {clay.Matrix3} a\n * @return {clay.Matrix3}\n */\nMatrix3.transpose = function (out, a) {\n mat3.transpose(out.array, a.array);\n out._dirty = true;\n return out;\n};\n\n/**\n * @param {clay.Matrix3} out\n * @param {clay.Matrix3} a\n * @param {clay.Vector2} v\n * @return {clay.Matrix3}\n */\nMatrix3.translate = function (out, a, v) {\n mat3.translate(out.array, a.array, v.array);\n out._dirty = true;\n return out;\n};\n\nexport default Matrix3;\n","import Animator from 'zrender/lib/animation/Animator';\nvar animatableMixin = {\n _animators: null,\n getAnimators: function () {\n this._animators = this._animators || [];\n return this._animators;\n },\n animate: function (path, opts) {\n this._animators = this._animators || [];\n var el = this;\n var target;\n\n if (path) {\n var pathSplitted = path.split('.');\n var prop = el;\n\n for (var i = 0, l = pathSplitted.length; i < l; i++) {\n if (!prop) {\n continue;\n }\n\n prop = prop[pathSplitted[i]];\n }\n\n if (prop) {\n target = prop;\n }\n } else {\n target = el;\n }\n\n if (target == null) {\n throw new Error('Target ' + path + ' not exists');\n }\n\n var animators = this._animators;\n var animator = new Animator(target, opts);\n var self = this;\n animator.during(function () {\n if (self.__zr) {\n self.__zr.refresh();\n }\n }).done(function () {\n var idx = animators.indexOf(animator);\n\n if (idx >= 0) {\n animators.splice(idx, 1);\n }\n });\n animators.push(animator);\n\n if (this.__zr) {\n this.__zr.animation.addAnimator(animator);\n }\n\n return animator;\n },\n stopAnimation: function (forwardToLast) {\n this._animators = this._animators || [];\n var animators = this._animators;\n var len = animators.length;\n\n for (var i = 0; i < len; i++) {\n animators[i].stop(forwardToLast);\n }\n\n animators.length = 0;\n return this;\n },\n addAnimatorsToZr: function (zr) {\n if (this._animators) {\n for (var i = 0; i < this._animators.length; i++) {\n zr.animation.addAnimator(this._animators[i]);\n }\n }\n },\n removeAnimatorsFromZr: function (zr) {\n if (this._animators) {\n for (var i = 0; i < this._animators.length; i++) {\n zr.animation.removeAnimator(this._animators[i]);\n }\n }\n }\n};\nexport default animatableMixin;","export default \"\\n@export clay.util.rand\\nhighp float rand(vec2 uv) {\\n const highp float a = 12.9898, b = 78.233, c = 43758.5453;\\n highp float dt = dot(uv.xy, vec2(a,b)), sn = mod(dt, 3.141592653589793);\\n return fract(sin(sn) * c);\\n}\\n@end\\n@export clay.util.calculate_attenuation\\nuniform float attenuationFactor : 5.0;\\nfloat lightAttenuation(float dist, float range)\\n{\\n float attenuation = 1.0;\\n attenuation = dist*dist/(range*range+1.0);\\n float att_s = attenuationFactor;\\n attenuation = 1.0/(attenuation*att_s+1.0);\\n att_s = 1.0/(att_s+1.0);\\n attenuation = attenuation - att_s;\\n attenuation /= 1.0 - att_s;\\n return clamp(attenuation, 0.0, 1.0);\\n}\\n@end\\n@export clay.util.edge_factor\\n#ifdef SUPPORT_STANDARD_DERIVATIVES\\nfloat edgeFactor(float width)\\n{\\n vec3 d = fwidth(v_Barycentric);\\n vec3 a3 = smoothstep(vec3(0.0), d * width, v_Barycentric);\\n return min(min(a3.x, a3.y), a3.z);\\n}\\n#else\\nfloat edgeFactor(float width)\\n{\\n return 1.0;\\n}\\n#endif\\n@end\\n@export clay.util.encode_float\\nvec4 encodeFloat(const in float depth)\\n{\\n const vec4 bitShifts = vec4(256.0*256.0*256.0, 256.0*256.0, 256.0, 1.0);\\n const vec4 bit_mask = vec4(0.0, 1.0/256.0, 1.0/256.0, 1.0/256.0);\\n vec4 res = fract(depth * bitShifts);\\n res -= res.xxyz * bit_mask;\\n return res;\\n}\\n@end\\n@export clay.util.decode_float\\nfloat decodeFloat(const in vec4 color)\\n{\\n const vec4 bitShifts = vec4(1.0/(256.0*256.0*256.0), 1.0/(256.0*256.0), 1.0/256.0, 1.0);\\n return dot(color, bitShifts);\\n}\\n@end\\n@export clay.util.float\\n@import clay.util.encode_float\\n@import clay.util.decode_float\\n@end\\n@export clay.util.rgbm_decode\\nvec3 RGBMDecode(vec4 rgbm, float range) {\\n return range * rgbm.rgb * rgbm.a;\\n}\\n@end\\n@export clay.util.rgbm_encode\\nvec4 RGBMEncode(vec3 color, float range) {\\n if (dot(color, color) == 0.0) {\\n return vec4(0.0);\\n }\\n vec4 rgbm;\\n color /= range;\\n rgbm.a = clamp(max(max(color.r, color.g), max(color.b, 1e-6)), 0.0, 1.0);\\n rgbm.a = ceil(rgbm.a * 255.0) / 255.0;\\n rgbm.rgb = color / rgbm.a;\\n return rgbm;\\n}\\n@end\\n@export clay.util.rgbm\\n@import clay.util.rgbm_decode\\n@import clay.util.rgbm_encode\\nvec4 decodeHDR(vec4 color)\\n{\\n#if defined(RGBM_DECODE) || defined(RGBM)\\n return vec4(RGBMDecode(color, 8.12), 1.0);\\n#else\\n return color;\\n#endif\\n}\\nvec4 encodeHDR(vec4 color)\\n{\\n#if defined(RGBM_ENCODE) || defined(RGBM)\\n return RGBMEncode(color.xyz, 8.12);\\n#else\\n return color;\\n#endif\\n}\\n@end\\n@export clay.util.srgb\\nvec4 sRGBToLinear(in vec4 value) {\\n return vec4(mix(pow(value.rgb * 0.9478672986 + vec3(0.0521327014), vec3(2.4)), value.rgb * 0.0773993808, vec3(lessThanEqual(value.rgb, vec3(0.04045)))), value.w);\\n}\\nvec4 linearTosRGB(in vec4 value) {\\n return vec4(mix(pow(value.rgb, vec3(0.41666)) * 1.055 - vec3(0.055), value.rgb * 12.92, vec3(lessThanEqual(value.rgb, vec3(0.0031308)))), value.w);\\n}\\n@end\\n@export clay.chunk.skinning_header\\n#ifdef SKINNING\\nattribute vec3 weight : WEIGHT;\\nattribute vec4 joint : JOINT;\\n#ifdef USE_SKIN_MATRICES_TEXTURE\\nuniform sampler2D skinMatricesTexture : ignore;\\nuniform float skinMatricesTextureSize: ignore;\\nmat4 getSkinMatrix(sampler2D tex, float idx) {\\n float j = idx * 4.0;\\n float x = mod(j, skinMatricesTextureSize);\\n float y = floor(j / skinMatricesTextureSize) + 0.5;\\n vec2 scale = vec2(skinMatricesTextureSize);\\n return mat4(\\n texture2D(tex, vec2(x + 0.5, y) / scale),\\n texture2D(tex, vec2(x + 1.5, y) / scale),\\n texture2D(tex, vec2(x + 2.5, y) / scale),\\n texture2D(tex, vec2(x + 3.5, y) / scale)\\n );\\n}\\nmat4 getSkinMatrix(float idx) {\\n return getSkinMatrix(skinMatricesTexture, idx);\\n}\\n#else\\nuniform mat4 skinMatrix[JOINT_COUNT] : SKIN_MATRIX;\\nmat4 getSkinMatrix(float idx) {\\n return skinMatrix[int(idx)];\\n}\\n#endif\\n#endif\\n@end\\n@export clay.chunk.skin_matrix\\nmat4 skinMatrixWS = getSkinMatrix(joint.x) * weight.x;\\nif (weight.y > 1e-4)\\n{\\n skinMatrixWS += getSkinMatrix(joint.y) * weight.y;\\n}\\nif (weight.z > 1e-4)\\n{\\n skinMatrixWS += getSkinMatrix(joint.z) * weight.z;\\n}\\nfloat weightW = 1.0-weight.x-weight.y-weight.z;\\nif (weightW > 1e-4)\\n{\\n skinMatrixWS += getSkinMatrix(joint.w) * weightW;\\n}\\n@end\\n@export clay.chunk.instancing_header\\n#ifdef INSTANCING\\nattribute vec4 instanceMat1;\\nattribute vec4 instanceMat2;\\nattribute vec4 instanceMat3;\\n#endif\\n@end\\n@export clay.chunk.instancing_matrix\\nmat4 instanceMat = mat4(\\n vec4(instanceMat1.xyz, 0.0),\\n vec4(instanceMat2.xyz, 0.0),\\n vec4(instanceMat3.xyz, 0.0),\\n vec4(instanceMat1.w, instanceMat2.w, instanceMat3.w, 1.0)\\n);\\n@end\\n@export clay.util.parallax_correct\\nvec3 parallaxCorrect(in vec3 dir, in vec3 pos, in vec3 boxMin, in vec3 boxMax) {\\n vec3 first = (boxMax - pos) / dir;\\n vec3 second = (boxMin - pos) / dir;\\n vec3 further = max(first, second);\\n float dist = min(further.x, min(further.y, further.z));\\n vec3 fixedPos = pos + dir * dist;\\n vec3 boxCenter = (boxMax + boxMin) * 0.5;\\n return normalize(fixedPos - boxCenter);\\n}\\n@end\\n@export clay.util.clamp_sample\\nvec4 clampSample(const in sampler2D texture, const in vec2 coord)\\n{\\n#ifdef STEREO\\n float eye = step(0.5, coord.x) * 0.5;\\n vec2 coordClamped = clamp(coord, vec2(eye, 0.0), vec2(0.5 + eye, 1.0));\\n#else\\n vec2 coordClamped = clamp(coord, vec2(0.0), vec2(1.0));\\n#endif\\n return texture2D(texture, coordClamped);\\n}\\n@end\\n@export clay.util.ACES\\nvec3 ACESToneMapping(vec3 color)\\n{\\n const float A = 2.51;\\n const float B = 0.03;\\n const float C = 2.43;\\n const float D = 0.59;\\n const float E = 0.14;\\n return (color * (A * color + B)) / (color * (C * color + D) + E);\\n}\\n@end\";\n","export default \"\\n@export ecgl.common.transformUniforms\\nuniform mat4 worldViewProjection : WORLDVIEWPROJECTION;\\nuniform mat4 worldInverseTranspose : WORLDINVERSETRANSPOSE;\\nuniform mat4 world : WORLD;\\n@end\\n\\n@export ecgl.common.attributes\\nattribute vec3 position : POSITION;\\nattribute vec2 texcoord : TEXCOORD_0;\\nattribute vec3 normal : NORMAL;\\n@end\\n\\n@export ecgl.common.uv.header\\nuniform vec2 uvRepeat : [1.0, 1.0];\\nuniform vec2 uvOffset : [0.0, 0.0];\\nuniform vec2 detailUvRepeat : [1.0, 1.0];\\nuniform vec2 detailUvOffset : [0.0, 0.0];\\n\\nvarying vec2 v_Texcoord;\\nvarying vec2 v_DetailTexcoord;\\n@end\\n\\n@export ecgl.common.uv.main\\nv_Texcoord = texcoord * uvRepeat + uvOffset;\\nv_DetailTexcoord = texcoord * detailUvRepeat + detailUvOffset;\\n@end\\n\\n@export ecgl.common.uv.fragmentHeader\\nvarying vec2 v_Texcoord;\\nvarying vec2 v_DetailTexcoord;\\n@end\\n\\n\\n@export ecgl.common.albedo.main\\n\\n vec4 albedoTexel = vec4(1.0);\\n#ifdef DIFFUSEMAP_ENABLED\\n albedoTexel = texture2D(diffuseMap, v_Texcoord);\\n #ifdef SRGB_DECODE\\n albedoTexel = sRGBToLinear(albedoTexel);\\n #endif\\n#endif\\n\\n#ifdef DETAILMAP_ENABLED\\n vec4 detailTexel = texture2D(detailMap, v_DetailTexcoord);\\n #ifdef SRGB_DECODE\\n detailTexel = sRGBToLinear(detailTexel);\\n #endif\\n albedoTexel.rgb = mix(albedoTexel.rgb, detailTexel.rgb, detailTexel.a);\\n albedoTexel.a = detailTexel.a + (1.0 - detailTexel.a) * albedoTexel.a;\\n#endif\\n\\n@end\\n\\n@export ecgl.common.wireframe.vertexHeader\\n\\n#ifdef WIREFRAME_QUAD\\nattribute vec4 barycentric;\\nvarying vec4 v_Barycentric;\\n#elif defined(WIREFRAME_TRIANGLE)\\nattribute vec3 barycentric;\\nvarying vec3 v_Barycentric;\\n#endif\\n\\n@end\\n\\n@export ecgl.common.wireframe.vertexMain\\n\\n#if defined(WIREFRAME_QUAD) || defined(WIREFRAME_TRIANGLE)\\n v_Barycentric = barycentric;\\n#endif\\n\\n@end\\n\\n\\n@export ecgl.common.wireframe.fragmentHeader\\n\\nuniform float wireframeLineWidth : 1;\\nuniform vec4 wireframeLineColor: [0, 0, 0, 0.5];\\n\\n#ifdef WIREFRAME_QUAD\\nvarying vec4 v_Barycentric;\\nfloat edgeFactor () {\\n vec4 d = fwidth(v_Barycentric);\\n vec4 a4 = smoothstep(vec4(0.0), d * wireframeLineWidth, v_Barycentric);\\n return min(min(min(a4.x, a4.y), a4.z), a4.w);\\n}\\n#elif defined(WIREFRAME_TRIANGLE)\\nvarying vec3 v_Barycentric;\\nfloat edgeFactor () {\\n vec3 d = fwidth(v_Barycentric);\\n vec3 a3 = smoothstep(vec3(0.0), d * wireframeLineWidth, v_Barycentric);\\n return min(min(a3.x, a3.y), a3.z);\\n}\\n#endif\\n\\n@end\\n\\n\\n@export ecgl.common.wireframe.fragmentMain\\n\\n#if defined(WIREFRAME_QUAD) || defined(WIREFRAME_TRIANGLE)\\n if (wireframeLineWidth > 0.) {\\n vec4 lineColor = wireframeLineColor;\\n#ifdef SRGB_DECODE\\n lineColor = sRGBToLinear(lineColor);\\n#endif\\n\\n gl_FragColor.rgb = mix(gl_FragColor.rgb, lineColor.rgb, (1.0 - edgeFactor()) * lineColor.a);\\n }\\n#endif\\n@end\\n\\n\\n\\n\\n@export ecgl.common.bumpMap.header\\n\\n#ifdef BUMPMAP_ENABLED\\nuniform sampler2D bumpMap;\\nuniform float bumpScale : 1.0;\\n\\n\\nvec3 bumpNormal(vec3 surfPos, vec3 surfNormal, vec3 baseNormal)\\n{\\n vec2 dSTdx = dFdx(v_Texcoord);\\n vec2 dSTdy = dFdy(v_Texcoord);\\n\\n float Hll = bumpScale * texture2D(bumpMap, v_Texcoord).x;\\n float dHx = bumpScale * texture2D(bumpMap, v_Texcoord + dSTdx).x - Hll;\\n float dHy = bumpScale * texture2D(bumpMap, v_Texcoord + dSTdy).x - Hll;\\n\\n vec3 vSigmaX = dFdx(surfPos);\\n vec3 vSigmaY = dFdy(surfPos);\\n vec3 vN = surfNormal;\\n\\n vec3 R1 = cross(vSigmaY, vN);\\n vec3 R2 = cross(vN, vSigmaX);\\n\\n float fDet = dot(vSigmaX, R1);\\n\\n vec3 vGrad = sign(fDet) * (dHx * R1 + dHy * R2);\\n return normalize(abs(fDet) * baseNormal - vGrad);\\n\\n}\\n#endif\\n\\n@end\\n\\n@export ecgl.common.normalMap.vertexHeader\\n\\n#ifdef NORMALMAP_ENABLED\\nattribute vec4 tangent : TANGENT;\\nvarying vec3 v_Tangent;\\nvarying vec3 v_Bitangent;\\n#endif\\n\\n@end\\n\\n@export ecgl.common.normalMap.vertexMain\\n\\n#ifdef NORMALMAP_ENABLED\\n if (dot(tangent, tangent) > 0.0) {\\n v_Tangent = normalize((worldInverseTranspose * vec4(tangent.xyz, 0.0)).xyz);\\n v_Bitangent = normalize(cross(v_Normal, v_Tangent) * tangent.w);\\n }\\n#endif\\n\\n@end\\n\\n\\n@export ecgl.common.normalMap.fragmentHeader\\n\\n#ifdef NORMALMAP_ENABLED\\nuniform sampler2D normalMap;\\nvarying vec3 v_Tangent;\\nvarying vec3 v_Bitangent;\\n#endif\\n\\n@end\\n\\n@export ecgl.common.normalMap.fragmentMain\\n#ifdef NORMALMAP_ENABLED\\n if (dot(v_Tangent, v_Tangent) > 0.0) {\\n vec3 normalTexel = texture2D(normalMap, v_DetailTexcoord).xyz;\\n if (dot(normalTexel, normalTexel) > 0.0) { N = normalTexel * 2.0 - 1.0;\\n mat3 tbn = mat3(v_Tangent, v_Bitangent, v_Normal);\\n N = normalize(tbn * N);\\n }\\n }\\n#endif\\n@end\\n\\n\\n\\n@export ecgl.common.vertexAnimation.header\\n\\n#ifdef VERTEX_ANIMATION\\nattribute vec3 prevPosition;\\nattribute vec3 prevNormal;\\nuniform float percent;\\n#endif\\n\\n@end\\n\\n@export ecgl.common.vertexAnimation.main\\n\\n#ifdef VERTEX_ANIMATION\\n vec3 pos = mix(prevPosition, position, percent);\\n vec3 norm = mix(prevNormal, normal, percent);\\n#else\\n vec3 pos = position;\\n vec3 norm = normal;\\n#endif\\n\\n@end\\n\\n\\n@export ecgl.common.ssaoMap.header\\n#ifdef SSAOMAP_ENABLED\\nuniform sampler2D ssaoMap;\\nuniform vec4 viewport : VIEWPORT;\\n#endif\\n@end\\n\\n@export ecgl.common.ssaoMap.main\\n float ao = 1.0;\\n#ifdef SSAOMAP_ENABLED\\n ao = texture2D(ssaoMap, (gl_FragCoord.xy - viewport.xy) / viewport.zw).r;\\n#endif\\n@end\\n\\n\\n\\n\\n@export ecgl.common.diffuseLayer.header\\n\\n#if (LAYER_DIFFUSEMAP_COUNT > 0)\\nuniform float layerDiffuseIntensity[LAYER_DIFFUSEMAP_COUNT];\\nuniform sampler2D layerDiffuseMap[LAYER_DIFFUSEMAP_COUNT];\\n#endif\\n\\n@end\\n\\n@export ecgl.common.emissiveLayer.header\\n\\n#if (LAYER_EMISSIVEMAP_COUNT > 0)\\nuniform float layerEmissionIntensity[LAYER_EMISSIVEMAP_COUNT];\\nuniform sampler2D layerEmissiveMap[LAYER_EMISSIVEMAP_COUNT];\\n#endif\\n\\n@end\\n\\n@export ecgl.common.layers.header\\n@import ecgl.common.diffuseLayer.header\\n@import ecgl.common.emissiveLayer.header\\n@end\\n\\n@export ecgl.common.diffuseLayer.main\\n\\n#if (LAYER_DIFFUSEMAP_COUNT > 0)\\n for (int _idx_ = 0; _idx_ < LAYER_DIFFUSEMAP_COUNT; _idx_++) {{\\n float intensity = layerDiffuseIntensity[_idx_];\\n vec4 texel2 = texture2D(layerDiffuseMap[_idx_], v_Texcoord);\\n #ifdef SRGB_DECODE\\n texel2 = sRGBToLinear(texel2);\\n #endif\\n albedoTexel.rgb = mix(albedoTexel.rgb, texel2.rgb * intensity, texel2.a);\\n albedoTexel.a = texel2.a + (1.0 - texel2.a) * albedoTexel.a;\\n }}\\n#endif\\n\\n@end\\n\\n@export ecgl.common.emissiveLayer.main\\n\\n#if (LAYER_EMISSIVEMAP_COUNT > 0)\\n for (int _idx_ = 0; _idx_ < LAYER_EMISSIVEMAP_COUNT; _idx_++)\\n {{\\n vec4 texel2 = texture2D(layerEmissiveMap[_idx_], v_Texcoord) * layerEmissionIntensity[_idx_];\\n #ifdef SRGB_DECODE\\n texel2 = sRGBToLinear(texel2);\\n #endif\\n float intensity = layerEmissionIntensity[_idx_];\\n gl_FragColor.rgb += texel2.rgb * texel2.a * intensity;\\n }}\\n#endif\\n\\n@end\\n\";","export default \"@export ecgl.color.vertex\\n\\nuniform mat4 worldViewProjection : WORLDVIEWPROJECTION;\\n\\n@import ecgl.common.uv.header\\n\\nattribute vec2 texcoord : TEXCOORD_0;\\nattribute vec3 position: POSITION;\\n\\n@import ecgl.common.wireframe.vertexHeader\\n\\n#ifdef VERTEX_COLOR\\nattribute vec4 a_Color : COLOR;\\nvarying vec4 v_Color;\\n#endif\\n\\n#ifdef VERTEX_ANIMATION\\nattribute vec3 prevPosition;\\nuniform float percent : 1.0;\\n#endif\\n\\n#ifdef ATMOSPHERE_ENABLED\\nattribute vec3 normal: NORMAL;\\nuniform mat4 worldInverseTranspose : WORLDINVERSETRANSPOSE;\\nvarying vec3 v_Normal;\\n#endif\\n\\nvoid main()\\n{\\n#ifdef VERTEX_ANIMATION\\n vec3 pos = mix(prevPosition, position, percent);\\n#else\\n vec3 pos = position;\\n#endif\\n\\n gl_Position = worldViewProjection * vec4(pos, 1.0);\\n\\n @import ecgl.common.uv.main\\n\\n#ifdef VERTEX_COLOR\\n v_Color = a_Color;\\n#endif\\n\\n#ifdef ATMOSPHERE_ENABLED\\n v_Normal = normalize((worldInverseTranspose * vec4(normal, 0.0)).xyz);\\n#endif\\n\\n @import ecgl.common.wireframe.vertexMain\\n\\n}\\n\\n@end\\n\\n@export ecgl.color.fragment\\n\\n#define LAYER_DIFFUSEMAP_COUNT 0\\n#define LAYER_EMISSIVEMAP_COUNT 0\\n\\nuniform sampler2D diffuseMap;\\nuniform sampler2D detailMap;\\n\\nuniform vec4 color : [1.0, 1.0, 1.0, 1.0];\\n\\n#ifdef ATMOSPHERE_ENABLED\\nuniform mat4 viewTranspose: VIEWTRANSPOSE;\\nuniform vec3 glowColor;\\nuniform float glowPower;\\nvarying vec3 v_Normal;\\n#endif\\n\\n#ifdef VERTEX_COLOR\\nvarying vec4 v_Color;\\n#endif\\n\\n@import ecgl.common.layers.header\\n\\n@import ecgl.common.uv.fragmentHeader\\n\\n@import ecgl.common.wireframe.fragmentHeader\\n\\n@import clay.util.srgb\\n\\nvoid main()\\n{\\n#ifdef SRGB_DECODE\\n gl_FragColor = sRGBToLinear(color);\\n#else\\n gl_FragColor = color;\\n#endif\\n\\n#ifdef VERTEX_COLOR\\n gl_FragColor *= v_Color;\\n#endif\\n\\n @import ecgl.common.albedo.main\\n\\n @import ecgl.common.diffuseLayer.main\\n\\n gl_FragColor *= albedoTexel;\\n\\n#ifdef ATMOSPHERE_ENABLED\\n float atmoIntensity = pow(1.0 - dot(v_Normal, (viewTranspose * vec4(0.0, 0.0, 1.0, 0.0)).xyz), glowPower);\\n gl_FragColor.rgb += glowColor * atmoIntensity;\\n#endif\\n\\n @import ecgl.common.emissiveLayer.main\\n\\n @import ecgl.common.wireframe.fragmentMain\\n\\n}\\n@end\";","export default \"/**\\n * http: */\\n\\n@export ecgl.lambert.vertex\\n\\n@import ecgl.common.transformUniforms\\n\\n@import ecgl.common.uv.header\\n\\n\\n@import ecgl.common.attributes\\n\\n@import ecgl.common.wireframe.vertexHeader\\n\\n#ifdef VERTEX_COLOR\\nattribute vec4 a_Color : COLOR;\\nvarying vec4 v_Color;\\n#endif\\n\\n\\n@import ecgl.common.vertexAnimation.header\\n\\n\\nvarying vec3 v_Normal;\\nvarying vec3 v_WorldPosition;\\n\\nvoid main()\\n{\\n @import ecgl.common.uv.main\\n\\n @import ecgl.common.vertexAnimation.main\\n\\n\\n gl_Position = worldViewProjection * vec4(pos, 1.0);\\n\\n v_Normal = normalize((worldInverseTranspose * vec4(norm, 0.0)).xyz);\\n v_WorldPosition = (world * vec4(pos, 1.0)).xyz;\\n\\n#ifdef VERTEX_COLOR\\n v_Color = a_Color;\\n#endif\\n\\n @import ecgl.common.wireframe.vertexMain\\n}\\n\\n@end\\n\\n\\n@export ecgl.lambert.fragment\\n\\n#define LAYER_DIFFUSEMAP_COUNT 0\\n#define LAYER_EMISSIVEMAP_COUNT 0\\n\\n#define NORMAL_UP_AXIS 1\\n#define NORMAL_FRONT_AXIS 2\\n\\n@import ecgl.common.uv.fragmentHeader\\n\\nvarying vec3 v_Normal;\\nvarying vec3 v_WorldPosition;\\n\\nuniform sampler2D diffuseMap;\\nuniform sampler2D detailMap;\\n\\n@import ecgl.common.layers.header\\n\\nuniform float emissionIntensity: 1.0;\\n\\nuniform vec4 color : [1.0, 1.0, 1.0, 1.0];\\n\\nuniform mat4 viewInverse : VIEWINVERSE;\\n\\n#ifdef ATMOSPHERE_ENABLED\\nuniform mat4 viewTranspose: VIEWTRANSPOSE;\\nuniform vec3 glowColor;\\nuniform float glowPower;\\n#endif\\n\\n#ifdef AMBIENT_LIGHT_COUNT\\n@import clay.header.ambient_light\\n#endif\\n#ifdef AMBIENT_SH_LIGHT_COUNT\\n@import clay.header.ambient_sh_light\\n#endif\\n\\n#ifdef DIRECTIONAL_LIGHT_COUNT\\n@import clay.header.directional_light\\n#endif\\n\\n#ifdef VERTEX_COLOR\\nvarying vec4 v_Color;\\n#endif\\n\\n\\n@import ecgl.common.ssaoMap.header\\n\\n@import ecgl.common.bumpMap.header\\n\\n@import clay.util.srgb\\n\\n@import ecgl.common.wireframe.fragmentHeader\\n\\n@import clay.plugin.compute_shadow_map\\n\\nvoid main()\\n{\\n#ifdef SRGB_DECODE\\n gl_FragColor = sRGBToLinear(color);\\n#else\\n gl_FragColor = color;\\n#endif\\n\\n#ifdef VERTEX_COLOR\\n #ifdef SRGB_DECODE\\n gl_FragColor *= sRGBToLinear(v_Color);\\n #else\\n gl_FragColor *= v_Color;\\n #endif\\n#endif\\n\\n @import ecgl.common.albedo.main\\n\\n @import ecgl.common.diffuseLayer.main\\n\\n gl_FragColor *= albedoTexel;\\n\\n vec3 N = v_Normal;\\n#ifdef DOUBLE_SIDED\\n vec3 eyePos = viewInverse[3].xyz;\\n vec3 V = normalize(eyePos - v_WorldPosition);\\n\\n if (dot(N, V) < 0.0) {\\n N = -N;\\n }\\n#endif\\n\\n float ambientFactor = 1.0;\\n\\n#ifdef BUMPMAP_ENABLED\\n N = bumpNormal(v_WorldPosition, v_Normal, N);\\n ambientFactor = dot(v_Normal, N);\\n#endif\\n\\n vec3 N2 = vec3(N.x, N[NORMAL_UP_AXIS], N[NORMAL_FRONT_AXIS]);\\n\\n vec3 diffuseColor = vec3(0.0, 0.0, 0.0);\\n\\n @import ecgl.common.ssaoMap.main\\n\\n#ifdef AMBIENT_LIGHT_COUNT\\n for(int i = 0; i < AMBIENT_LIGHT_COUNT; i++)\\n {\\n diffuseColor += ambientLightColor[i] * ambientFactor * ao;\\n }\\n#endif\\n#ifdef AMBIENT_SH_LIGHT_COUNT\\n for(int _idx_ = 0; _idx_ < AMBIENT_SH_LIGHT_COUNT; _idx_++)\\n {{\\n diffuseColor += calcAmbientSHLight(_idx_, N2) * ambientSHLightColor[_idx_] * ao;\\n }}\\n#endif\\n#ifdef DIRECTIONAL_LIGHT_COUNT\\n#if defined(DIRECTIONAL_LIGHT_SHADOWMAP_COUNT)\\n float shadowContribsDir[DIRECTIONAL_LIGHT_COUNT];\\n if(shadowEnabled)\\n {\\n computeShadowOfDirectionalLights(v_WorldPosition, shadowContribsDir);\\n }\\n#endif\\n for(int i = 0; i < DIRECTIONAL_LIGHT_COUNT; i++)\\n {\\n vec3 lightDirection = -directionalLightDirection[i];\\n vec3 lightColor = directionalLightColor[i];\\n\\n float shadowContrib = 1.0;\\n#if defined(DIRECTIONAL_LIGHT_SHADOWMAP_COUNT)\\n if (shadowEnabled)\\n {\\n shadowContrib = shadowContribsDir[i];\\n }\\n#endif\\n\\n float ndl = dot(N, normalize(lightDirection)) * shadowContrib;\\n\\n diffuseColor += lightColor * clamp(ndl, 0.0, 1.0);\\n }\\n#endif\\n\\n gl_FragColor.rgb *= diffuseColor;\\n\\n#ifdef ATMOSPHERE_ENABLED\\n float atmoIntensity = pow(1.0 - dot(v_Normal, (viewTranspose * vec4(0.0, 0.0, 1.0, 0.0)).xyz), glowPower);\\n gl_FragColor.rgb += glowColor * atmoIntensity;\\n#endif\\n\\n @import ecgl.common.emissiveLayer.main\\n\\n @import ecgl.common.wireframe.fragmentMain\\n}\\n\\n@end\";","export default \"@export ecgl.realistic.vertex\\n\\n@import ecgl.common.transformUniforms\\n\\n@import ecgl.common.uv.header\\n\\n@import ecgl.common.attributes\\n\\n\\n@import ecgl.common.wireframe.vertexHeader\\n\\n#ifdef VERTEX_COLOR\\nattribute vec4 a_Color : COLOR;\\nvarying vec4 v_Color;\\n#endif\\n\\n#ifdef NORMALMAP_ENABLED\\nattribute vec4 tangent : TANGENT;\\nvarying vec3 v_Tangent;\\nvarying vec3 v_Bitangent;\\n#endif\\n\\n@import ecgl.common.vertexAnimation.header\\n\\nvarying vec3 v_Normal;\\nvarying vec3 v_WorldPosition;\\n\\nvoid main()\\n{\\n\\n @import ecgl.common.uv.main\\n\\n @import ecgl.common.vertexAnimation.main\\n\\n gl_Position = worldViewProjection * vec4(pos, 1.0);\\n\\n v_Normal = normalize((worldInverseTranspose * vec4(norm, 0.0)).xyz);\\n v_WorldPosition = (world * vec4(pos, 1.0)).xyz;\\n\\n#ifdef VERTEX_COLOR\\n v_Color = a_Color;\\n#endif\\n\\n#ifdef NORMALMAP_ENABLED\\n v_Tangent = normalize((worldInverseTranspose * vec4(tangent.xyz, 0.0)).xyz);\\n v_Bitangent = normalize(cross(v_Normal, v_Tangent) * tangent.w);\\n#endif\\n\\n @import ecgl.common.wireframe.vertexMain\\n\\n}\\n\\n@end\\n\\n\\n\\n@export ecgl.realistic.fragment\\n\\n#define LAYER_DIFFUSEMAP_COUNT 0\\n#define LAYER_EMISSIVEMAP_COUNT 0\\n#define PI 3.14159265358979\\n#define ROUGHNESS_CHANEL 0\\n#define METALNESS_CHANEL 1\\n\\n#define NORMAL_UP_AXIS 1\\n#define NORMAL_FRONT_AXIS 2\\n\\n#ifdef VERTEX_COLOR\\nvarying vec4 v_Color;\\n#endif\\n\\n@import ecgl.common.uv.fragmentHeader\\n\\nvarying vec3 v_Normal;\\nvarying vec3 v_WorldPosition;\\n\\nuniform sampler2D diffuseMap;\\n\\nuniform sampler2D detailMap;\\nuniform sampler2D metalnessMap;\\nuniform sampler2D roughnessMap;\\n\\n@import ecgl.common.layers.header\\n\\nuniform float emissionIntensity: 1.0;\\n\\nuniform vec4 color : [1.0, 1.0, 1.0, 1.0];\\n\\nuniform float metalness : 0.0;\\nuniform float roughness : 0.5;\\n\\nuniform mat4 viewInverse : VIEWINVERSE;\\n\\n#ifdef ATMOSPHERE_ENABLED\\nuniform mat4 viewTranspose: VIEWTRANSPOSE;\\nuniform vec3 glowColor;\\nuniform float glowPower;\\n#endif\\n\\n#ifdef AMBIENT_LIGHT_COUNT\\n@import clay.header.ambient_light\\n#endif\\n\\n#ifdef AMBIENT_SH_LIGHT_COUNT\\n@import clay.header.ambient_sh_light\\n#endif\\n\\n#ifdef AMBIENT_CUBEMAP_LIGHT_COUNT\\n@import clay.header.ambient_cubemap_light\\n#endif\\n\\n#ifdef DIRECTIONAL_LIGHT_COUNT\\n@import clay.header.directional_light\\n#endif\\n\\n@import ecgl.common.normalMap.fragmentHeader\\n\\n@import ecgl.common.ssaoMap.header\\n\\n@import ecgl.common.bumpMap.header\\n\\n@import clay.util.srgb\\n\\n@import clay.util.rgbm\\n\\n@import ecgl.common.wireframe.fragmentHeader\\n\\n@import clay.plugin.compute_shadow_map\\n\\nvec3 F_Schlick(float ndv, vec3 spec) {\\n return spec + (1.0 - spec) * pow(1.0 - ndv, 5.0);\\n}\\n\\nfloat D_Phong(float g, float ndh) {\\n float a = pow(8192.0, g);\\n return (a + 2.0) / 8.0 * pow(ndh, a);\\n}\\n\\nvoid main()\\n{\\n vec4 albedoColor = color;\\n\\n vec3 eyePos = viewInverse[3].xyz;\\n vec3 V = normalize(eyePos - v_WorldPosition);\\n#ifdef VERTEX_COLOR\\n #ifdef SRGB_DECODE\\n albedoColor *= sRGBToLinear(v_Color);\\n #else\\n albedoColor *= v_Color;\\n #endif\\n#endif\\n\\n @import ecgl.common.albedo.main\\n\\n @import ecgl.common.diffuseLayer.main\\n\\n albedoColor *= albedoTexel;\\n\\n float m = metalness;\\n\\n#ifdef METALNESSMAP_ENABLED\\n float m2 = texture2D(metalnessMap, v_DetailTexcoord)[METALNESS_CHANEL];\\n m = clamp(m2 + (m - 0.5) * 2.0, 0.0, 1.0);\\n#endif\\n\\n vec3 baseColor = albedoColor.rgb;\\n albedoColor.rgb = baseColor * (1.0 - m);\\n vec3 specFactor = mix(vec3(0.04), baseColor, m);\\n\\n float g = 1.0 - roughness;\\n\\n#ifdef ROUGHNESSMAP_ENABLED\\n float g2 = 1.0 - texture2D(roughnessMap, v_DetailTexcoord)[ROUGHNESS_CHANEL];\\n g = clamp(g2 + (g - 0.5) * 2.0, 0.0, 1.0);\\n#endif\\n\\n vec3 N = v_Normal;\\n\\n#ifdef DOUBLE_SIDED\\n if (dot(N, V) < 0.0) {\\n N = -N;\\n }\\n#endif\\n\\n float ambientFactor = 1.0;\\n\\n#ifdef BUMPMAP_ENABLED\\n N = bumpNormal(v_WorldPosition, v_Normal, N);\\n ambientFactor = dot(v_Normal, N);\\n#endif\\n\\n@import ecgl.common.normalMap.fragmentMain\\n\\n vec3 N2 = vec3(N.x, N[NORMAL_UP_AXIS], N[NORMAL_FRONT_AXIS]);\\n\\n vec3 diffuseTerm = vec3(0.0);\\n vec3 specularTerm = vec3(0.0);\\n\\n float ndv = clamp(dot(N, V), 0.0, 1.0);\\n vec3 fresnelTerm = F_Schlick(ndv, specFactor);\\n\\n @import ecgl.common.ssaoMap.main\\n\\n#ifdef AMBIENT_LIGHT_COUNT\\n for(int _idx_ = 0; _idx_ < AMBIENT_LIGHT_COUNT; _idx_++)\\n {{\\n diffuseTerm += ambientLightColor[_idx_] * ambientFactor * ao;\\n }}\\n#endif\\n\\n#ifdef AMBIENT_SH_LIGHT_COUNT\\n for(int _idx_ = 0; _idx_ < AMBIENT_SH_LIGHT_COUNT; _idx_++)\\n {{\\n diffuseTerm += calcAmbientSHLight(_idx_, N2) * ambientSHLightColor[_idx_] * ao;\\n }}\\n#endif\\n\\n#ifdef DIRECTIONAL_LIGHT_COUNT\\n#if defined(DIRECTIONAL_LIGHT_SHADOWMAP_COUNT)\\n float shadowContribsDir[DIRECTIONAL_LIGHT_COUNT];\\n if(shadowEnabled)\\n {\\n computeShadowOfDirectionalLights(v_WorldPosition, shadowContribsDir);\\n }\\n#endif\\n for(int _idx_ = 0; _idx_ < DIRECTIONAL_LIGHT_COUNT; _idx_++)\\n {{\\n vec3 L = -directionalLightDirection[_idx_];\\n vec3 lc = directionalLightColor[_idx_];\\n\\n vec3 H = normalize(L + V);\\n float ndl = clamp(dot(N, normalize(L)), 0.0, 1.0);\\n float ndh = clamp(dot(N, H), 0.0, 1.0);\\n\\n float shadowContrib = 1.0;\\n#if defined(DIRECTIONAL_LIGHT_SHADOWMAP_COUNT)\\n if (shadowEnabled)\\n {\\n shadowContrib = shadowContribsDir[_idx_];\\n }\\n#endif\\n\\n vec3 li = lc * ndl * shadowContrib;\\n\\n diffuseTerm += li;\\n specularTerm += li * fresnelTerm * D_Phong(g, ndh);\\n }}\\n#endif\\n\\n\\n#ifdef AMBIENT_CUBEMAP_LIGHT_COUNT\\n vec3 L = reflect(-V, N);\\n L = vec3(L.x, L[NORMAL_UP_AXIS], L[NORMAL_FRONT_AXIS]);\\n float rough2 = clamp(1.0 - g, 0.0, 1.0);\\n float bias2 = rough2 * 5.0;\\n vec2 brdfParam2 = texture2D(ambientCubemapLightBRDFLookup[0], vec2(rough2, ndv)).xy;\\n vec3 envWeight2 = specFactor * brdfParam2.x + brdfParam2.y;\\n vec3 envTexel2;\\n for(int _idx_ = 0; _idx_ < AMBIENT_CUBEMAP_LIGHT_COUNT; _idx_++)\\n {{\\n envTexel2 = RGBMDecode(textureCubeLodEXT(ambientCubemapLightCubemap[_idx_], L, bias2), 8.12);\\n specularTerm += ambientCubemapLightColor[_idx_] * envTexel2 * envWeight2 * ao;\\n }}\\n#endif\\n\\n gl_FragColor.rgb = albedoColor.rgb * diffuseTerm + specularTerm;\\n gl_FragColor.a = albedoColor.a;\\n\\n#ifdef ATMOSPHERE_ENABLED\\n float atmoIntensity = pow(1.0 - dot(v_Normal, (viewTranspose * vec4(0.0, 0.0, 1.0, 0.0)).xyz), glowPower);\\n gl_FragColor.rgb += glowColor * atmoIntensity;\\n#endif\\n\\n#ifdef SRGB_ENCODE\\n gl_FragColor = linearTosRGB(gl_FragColor);\\n#endif\\n\\n @import ecgl.common.emissiveLayer.main\\n\\n @import ecgl.common.wireframe.fragmentMain\\n}\\n\\n@end\";","export default \"@export ecgl.hatching.vertex\\n\\n@import ecgl.realistic.vertex\\n\\n@end\\n\\n\\n@export ecgl.hatching.fragment\\n\\n#define NORMAL_UP_AXIS 1\\n#define NORMAL_FRONT_AXIS 2\\n\\n@import ecgl.common.uv.fragmentHeader\\n\\nvarying vec3 v_Normal;\\nvarying vec3 v_WorldPosition;\\n\\nuniform vec4 color : [0.0, 0.0, 0.0, 1.0];\\nuniform vec4 paperColor : [1.0, 1.0, 1.0, 1.0];\\n\\nuniform mat4 viewInverse : VIEWINVERSE;\\n\\n#ifdef AMBIENT_LIGHT_COUNT\\n@import clay.header.ambient_light\\n#endif\\n#ifdef AMBIENT_SH_LIGHT_COUNT\\n@import clay.header.ambient_sh_light\\n#endif\\n\\n#ifdef DIRECTIONAL_LIGHT_COUNT\\n@import clay.header.directional_light\\n#endif\\n\\n#ifdef VERTEX_COLOR\\nvarying vec4 v_Color;\\n#endif\\n\\n\\n@import ecgl.common.ssaoMap.header\\n\\n@import ecgl.common.bumpMap.header\\n\\n@import clay.util.srgb\\n\\n@import ecgl.common.wireframe.fragmentHeader\\n\\n@import clay.plugin.compute_shadow_map\\n\\nuniform sampler2D hatch1;\\nuniform sampler2D hatch2;\\nuniform sampler2D hatch3;\\nuniform sampler2D hatch4;\\nuniform sampler2D hatch5;\\nuniform sampler2D hatch6;\\n\\nfloat shade(in float tone) {\\n vec4 c = vec4(1. ,1., 1., 1.);\\n float step = 1. / 6.;\\n vec2 uv = v_DetailTexcoord;\\n if (tone <= step / 2.0) {\\n c = mix(vec4(0.), texture2D(hatch6, uv), 12. * tone);\\n }\\n else if (tone <= step) {\\n c = mix(texture2D(hatch6, uv), texture2D(hatch5, uv), 6. * tone);\\n }\\n if(tone > step && tone <= 2. * step){\\n c = mix(texture2D(hatch5, uv), texture2D(hatch4, uv) , 6. * (tone - step));\\n }\\n if(tone > 2. * step && tone <= 3. * step){\\n c = mix(texture2D(hatch4, uv), texture2D(hatch3, uv), 6. * (tone - 2. * step));\\n }\\n if(tone > 3. * step && tone <= 4. * step){\\n c = mix(texture2D(hatch3, uv), texture2D(hatch2, uv), 6. * (tone - 3. * step));\\n }\\n if(tone > 4. * step && tone <= 5. * step){\\n c = mix(texture2D(hatch2, uv), texture2D(hatch1, uv), 6. * (tone - 4. * step));\\n }\\n if(tone > 5. * step){\\n c = mix(texture2D(hatch1, uv), vec4(1.), 6. * (tone - 5. * step));\\n }\\n\\n return c.r;\\n}\\n\\nconst vec3 w = vec3(0.2125, 0.7154, 0.0721);\\n\\nvoid main()\\n{\\n#ifdef SRGB_DECODE\\n vec4 inkColor = sRGBToLinear(color);\\n#else\\n vec4 inkColor = color;\\n#endif\\n\\n#ifdef VERTEX_COLOR\\n #ifdef SRGB_DECODE\\n inkColor *= sRGBToLinear(v_Color);\\n #else\\n inkColor *= v_Color;\\n #endif\\n#endif\\n\\n vec3 N = v_Normal;\\n#ifdef DOUBLE_SIDED\\n vec3 eyePos = viewInverse[3].xyz;\\n vec3 V = normalize(eyePos - v_WorldPosition);\\n\\n if (dot(N, V) < 0.0) {\\n N = -N;\\n }\\n#endif\\n\\n float tone = 0.0;\\n\\n float ambientFactor = 1.0;\\n\\n#ifdef BUMPMAP_ENABLED\\n N = bumpNormal(v_WorldPosition, v_Normal, N);\\n ambientFactor = dot(v_Normal, N);\\n#endif\\n\\n vec3 N2 = vec3(N.x, N[NORMAL_UP_AXIS], N[NORMAL_FRONT_AXIS]);\\n\\n @import ecgl.common.ssaoMap.main\\n\\n#ifdef AMBIENT_LIGHT_COUNT\\n for(int i = 0; i < AMBIENT_LIGHT_COUNT; i++)\\n {\\n tone += dot(ambientLightColor[i], w) * ambientFactor * ao;\\n }\\n#endif\\n#ifdef AMBIENT_SH_LIGHT_COUNT\\n for(int _idx_ = 0; _idx_ < AMBIENT_SH_LIGHT_COUNT; _idx_++)\\n {{\\n tone += dot(calcAmbientSHLight(_idx_, N2) * ambientSHLightColor[_idx_], w) * ao;\\n }}\\n#endif\\n#ifdef DIRECTIONAL_LIGHT_COUNT\\n#if defined(DIRECTIONAL_LIGHT_SHADOWMAP_COUNT)\\n float shadowContribsDir[DIRECTIONAL_LIGHT_COUNT];\\n if(shadowEnabled)\\n {\\n computeShadowOfDirectionalLights(v_WorldPosition, shadowContribsDir);\\n }\\n#endif\\n for(int i = 0; i < DIRECTIONAL_LIGHT_COUNT; i++)\\n {\\n vec3 lightDirection = -directionalLightDirection[i];\\n float lightTone = dot(directionalLightColor[i], w);\\n\\n float shadowContrib = 1.0;\\n#if defined(DIRECTIONAL_LIGHT_SHADOWMAP_COUNT)\\n if (shadowEnabled)\\n {\\n shadowContrib = shadowContribsDir[i];\\n }\\n#endif\\n\\n float ndl = dot(N, normalize(lightDirection)) * shadowContrib;\\n\\n tone += lightTone * clamp(ndl, 0.0, 1.0);\\n }\\n#endif\\n\\n gl_FragColor = mix(inkColor, paperColor, shade(clamp(tone, 0.0, 1.0)));\\n }\\n@end\\n\";","export default \"@export ecgl.sm.depth.vertex\\n\\nuniform mat4 worldViewProjection : WORLDVIEWPROJECTION;\\n\\nattribute vec3 position : POSITION;\\nattribute vec2 texcoord : TEXCOORD_0;\\n\\n#ifdef VERTEX_ANIMATION\\nattribute vec3 prevPosition;\\nuniform float percent : 1.0;\\n#endif\\n\\nvarying vec4 v_ViewPosition;\\nvarying vec2 v_Texcoord;\\n\\nvoid main(){\\n\\n#ifdef VERTEX_ANIMATION\\n vec3 pos = mix(prevPosition, position, percent);\\n#else\\n vec3 pos = position;\\n#endif\\n\\n v_ViewPosition = worldViewProjection * vec4(pos, 1.0);\\n gl_Position = v_ViewPosition;\\n\\n v_Texcoord = texcoord;\\n\\n}\\n@end\\n\\n\\n\\n@export ecgl.sm.depth.fragment\\n\\n@import clay.sm.depth.fragment\\n\\n@end\";","import Mesh from 'claygl/src/Mesh';\nimport Renderer from 'claygl/src/Renderer';\nimport Texture2D from 'claygl/src/Texture2D';\nimport Texture from 'claygl/src/Texture';\nimport Shader from 'claygl/src/Shader';\nimport Material from 'claygl/src/Material';\nimport Node3D from 'claygl/src/Node';\nimport Geometry from 'claygl/src/Geometry';\nimport * as echarts from 'echarts/lib/echarts';\nimport Scene from 'claygl/src/Scene';\nimport LRUCache from 'zrender/lib/core/LRU';\nimport textureUtil from 'claygl/src/util/texture';\nimport EChartsSurface from './EChartsSurface';\nimport AmbientCubemapLight from 'claygl/src/light/AmbientCubemap';\nimport AmbientSHLight from 'claygl/src/light/AmbientSH';\nimport shUtil from 'claygl/src/util/sh';\nimport retrieve from './retrieve';\nimport SphereGeometry from 'claygl/src/geometry/Sphere';\nimport PlaneGeometry from 'claygl/src/geometry/Plane';\nimport CubeGeometry from 'claygl/src/geometry/Cube';\nimport AmbientLight from 'claygl/src/light/Ambient';\nimport DirectionalLight from 'claygl/src/light/Directional';\nimport PointLight from 'claygl/src/light/Point';\nimport SpotLight from 'claygl/src/light/Spot';\nimport PerspectiveCamera from 'claygl/src/camera/Perspective';\nimport OrthographicCamera from 'claygl/src/camera/Orthographic'; // Math\n\nimport Vector2 from 'claygl/src/math/Vector2';\nimport Vector3 from 'claygl/src/math/Vector3';\nimport Vector4 from 'claygl/src/math/Vector4';\nimport Quaternion from 'claygl/src/math/Quaternion';\nimport Matrix2 from 'claygl/src/math/Matrix2';\nimport Matrix2d from 'claygl/src/math/Matrix2d';\nimport Matrix3 from 'claygl/src/math/Matrix3';\nimport Matrix4 from 'claygl/src/math/Matrix4';\nimport Plane from 'claygl/src/math/Plane';\nimport Ray from 'claygl/src/math/Ray';\nimport BoundingBox from 'claygl/src/math/BoundingBox';\nimport Frustum from 'claygl/src/math/Frustum';\nimport animatableMixin from './animatableMixin'; // Some common shaders\n\nimport utilGLSL from 'claygl/src/shader/source/util.glsl.js';\nimport prezGLSL from 'claygl/src/shader/source/prez.glsl.js';\nimport commonGLSL from './shader/common.glsl.js';\nimport colorGLSL from './shader/color.glsl.js';\nimport lambertGLSL from './shader/lambert.glsl.js';\nimport realisticGLSL from './shader/realistic.glsl.js';\nimport hatchingGLSL from './shader/hatching.glsl.js';\nimport shadowGLSL from './shader/shadow.glsl.js';\nObject.assign(Node3D.prototype, animatableMixin);\nShader.import(utilGLSL);\nShader.import(prezGLSL);\nShader.import(commonGLSL);\nShader.import(colorGLSL);\nShader.import(lambertGLSL);\nShader.import(realisticGLSL);\nShader.import(hatchingGLSL);\nShader.import(shadowGLSL);\n\nfunction isValueNone(value) {\n return !value || value === 'none';\n}\n\nfunction isValueImage(value) {\n return value instanceof HTMLCanvasElement || value instanceof HTMLImageElement || value instanceof Image;\n}\n\nfunction isECharts(value) {\n return value.getZr && value.setOption;\n} // Overwrite addToScene and removeFromScene\n\n\nvar oldAddToScene = Scene.prototype.addToScene;\nvar oldRemoveFromScene = Scene.prototype.removeFromScene;\n\nScene.prototype.addToScene = function (node) {\n oldAddToScene.call(this, node);\n\n if (this.__zr) {\n var zr = this.__zr;\n node.traverse(function (child) {\n child.__zr = zr;\n\n if (child.addAnimatorsToZr) {\n child.addAnimatorsToZr(zr);\n }\n });\n }\n};\n\nScene.prototype.removeFromScene = function (node) {\n oldRemoveFromScene.call(this, node);\n node.traverse(function (child) {\n var zr = child.__zr;\n child.__zr = null;\n\n if (zr && child.removeAnimatorsFromZr) {\n child.removeAnimatorsFromZr(zr);\n }\n });\n};\n/**\n * @param {string} textureName\n * @param {string|HTMLImageElement|HTMLCanvasElement} imgValue\n * @param {module:echarts/ExtensionAPI} api\n * @param {Object} [textureOpts]\n */\n\n\nMaterial.prototype.setTextureImage = function (textureName, imgValue, api, textureOpts) {\n if (!this.shader) {\n return;\n }\n\n var zr = api.getZr();\n var material = this;\n var texture;\n material.autoUpdateTextureStatus = false; // disableTexture first\n\n material.disableTexture(textureName);\n\n if (!isValueNone(imgValue)) {\n texture = graphicGL.loadTexture(imgValue, api, textureOpts, function (texture) {\n material.enableTexture(textureName);\n zr && zr.refresh();\n }); // Set texture immediately for other code to verify if have this texture.\n\n material.set(textureName, texture);\n }\n\n return texture;\n};\n\nvar graphicGL = {};\ngraphicGL.Renderer = Renderer;\ngraphicGL.Node = Node3D;\ngraphicGL.Mesh = Mesh;\ngraphicGL.Shader = Shader;\ngraphicGL.Material = Material;\ngraphicGL.Texture = Texture;\ngraphicGL.Texture2D = Texture2D; // Geometries\n\ngraphicGL.Geometry = Geometry;\ngraphicGL.SphereGeometry = SphereGeometry;\ngraphicGL.PlaneGeometry = PlaneGeometry;\ngraphicGL.CubeGeometry = CubeGeometry; // Lights\n\ngraphicGL.AmbientLight = AmbientLight;\ngraphicGL.DirectionalLight = DirectionalLight;\ngraphicGL.PointLight = PointLight;\ngraphicGL.SpotLight = SpotLight; // Cameras\n\ngraphicGL.PerspectiveCamera = PerspectiveCamera;\ngraphicGL.OrthographicCamera = OrthographicCamera; // Math\n\ngraphicGL.Vector2 = Vector2;\ngraphicGL.Vector3 = Vector3;\ngraphicGL.Vector4 = Vector4;\ngraphicGL.Quaternion = Quaternion;\ngraphicGL.Matrix2 = Matrix2;\ngraphicGL.Matrix2d = Matrix2d;\ngraphicGL.Matrix3 = Matrix3;\ngraphicGL.Matrix4 = Matrix4;\ngraphicGL.Plane = Plane;\ngraphicGL.Ray = Ray;\ngraphicGL.BoundingBox = BoundingBox;\ngraphicGL.Frustum = Frustum; // Texture utilities\n\nvar blankImage = null;\n\nfunction getBlankImage() {\n if (blankImage !== null) {\n return blankImage;\n }\n\n blankImage = textureUtil.createBlank('rgba(255,255,255,0)').image;\n return blankImage;\n}\n\nfunction nearestPowerOfTwo(val) {\n return Math.pow(2, Math.round(Math.log(val) / Math.LN2));\n}\n\nfunction convertTextureToPowerOfTwo(texture) {\n if ((texture.wrapS === Texture.REPEAT || texture.wrapT === Texture.REPEAT) && texture.image) {\n // var canvas = document.createElement('canvas');\n var width = nearestPowerOfTwo(texture.width);\n var height = nearestPowerOfTwo(texture.height);\n\n if (width !== texture.width || height !== texture.height) {\n var canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n var ctx = canvas.getContext('2d');\n ctx.drawImage(texture.image, 0, 0, width, height);\n texture.image = canvas;\n }\n }\n}\n/**\n * @param {string|HTMLImageElement|HTMLCanvasElement} imgValue\n * @param {module:echarts/ExtensionAPI} api\n * @param {Object} [textureOpts]\n * @param {Function} cb\n */\n// TODO Promise, test\n\n\ngraphicGL.loadTexture = function (imgValue, api, textureOpts, cb) {\n if (typeof textureOpts === 'function') {\n cb = textureOpts;\n textureOpts = {};\n }\n\n textureOpts = textureOpts || {};\n var keys = Object.keys(textureOpts).sort();\n var prefix = '';\n\n for (var i = 0; i < keys.length; i++) {\n prefix += keys[i] + '_' + textureOpts[keys[i]] + '_';\n }\n\n var textureCache = api.__textureCache = api.__textureCache || new LRUCache(20);\n\n if (isECharts(imgValue)) {\n var id = imgValue.__textureid__;\n var textureObj = textureCache.get(prefix + id);\n\n if (!textureObj) {\n var surface = new EChartsSurface(imgValue);\n\n surface.onupdate = function () {\n api.getZr().refresh();\n };\n\n textureObj = {\n texture: surface.getTexture()\n };\n\n for (var i = 0; i < keys.length; i++) {\n textureObj.texture[keys[i]] = textureOpts[keys[i]];\n }\n\n id = imgValue.__textureid__ || '__ecgl_ec__' + textureObj.texture.__uid__;\n imgValue.__textureid__ = id;\n textureCache.put(prefix + id, textureObj);\n cb && cb(textureObj.texture);\n } else {\n textureObj.texture.surface.setECharts(imgValue);\n cb && cb(textureObj.texture);\n }\n\n return textureObj.texture;\n } else if (isValueImage(imgValue)) {\n var id = imgValue.__textureid__;\n var textureObj = textureCache.get(prefix + id);\n\n if (!textureObj) {\n textureObj = {\n texture: new graphicGL.Texture2D({\n image: imgValue\n })\n };\n\n for (var i = 0; i < keys.length; i++) {\n textureObj.texture[keys[i]] = textureOpts[keys[i]];\n }\n\n id = imgValue.__textureid__ || '__ecgl_image__' + textureObj.texture.__uid__;\n imgValue.__textureid__ = id;\n textureCache.put(prefix + id, textureObj);\n convertTextureToPowerOfTwo(textureObj.texture); // TODO Next tick?\n\n cb && cb(textureObj.texture);\n }\n\n return textureObj.texture;\n } else {\n var textureObj = textureCache.get(prefix + imgValue);\n\n if (textureObj) {\n if (textureObj.callbacks) {\n // Add to pending callbacks\n textureObj.callbacks.push(cb);\n } else {\n // TODO Next tick?\n cb && cb(textureObj.texture);\n }\n } else {\n // Maybe base64\n if (imgValue.match(/.hdr$|^data:application\\/octet-stream/)) {\n textureObj = {\n callbacks: [cb]\n };\n var texture = textureUtil.loadTexture(imgValue, {\n exposure: textureOpts.exposure,\n fileType: 'hdr'\n }, function () {\n texture.dirty();\n textureObj.callbacks.forEach(function (cb) {\n cb && cb(texture);\n });\n textureObj.callbacks = null;\n });\n textureObj.texture = texture;\n textureCache.put(prefix + imgValue, textureObj);\n } else {\n var texture = new graphicGL.Texture2D({\n image: new Image()\n });\n\n for (var i = 0; i < keys.length; i++) {\n texture[keys[i]] = textureOpts[keys[i]];\n }\n\n textureObj = {\n texture: texture,\n callbacks: [cb]\n };\n var originalImage = texture.image;\n\n originalImage.onload = function () {\n texture.image = originalImage;\n convertTextureToPowerOfTwo(texture);\n texture.dirty();\n textureObj.callbacks.forEach(function (cb) {\n cb && cb(texture);\n });\n textureObj.callbacks = null;\n };\n\n originalImage.crossOrigin = 'Anonymous';\n originalImage.src = imgValue; // Use blank image as place holder.\n\n texture.image = getBlankImage();\n textureCache.put(prefix + imgValue, textureObj);\n }\n }\n\n return textureObj.texture;\n }\n};\n/**\n * Create ambientCubemap and ambientSH light. respectively to have specular and diffuse light\n * @return {Object} { specular, diffuse }\n */\n\n\ngraphicGL.createAmbientCubemap = function (opt, renderer, api, cb) {\n opt = opt || {};\n var textureUrl = opt.texture;\n var exposure = retrieve.firstNotNull(opt.exposure, 1.0);\n var ambientCubemap = new AmbientCubemapLight({\n intensity: retrieve.firstNotNull(opt.specularIntensity, 1.0)\n });\n var ambientSH = new AmbientSHLight({\n intensity: retrieve.firstNotNull(opt.diffuseIntensity, 1.0),\n coefficients: [0.844, 0.712, 0.691, -0.037, 0.083, 0.167, 0.343, 0.288, 0.299, -0.041, -0.021, -0.009, -0.003, -0.041, -0.064, -0.011, -0.007, -0.004, -0.031, 0.034, 0.081, -0.060, -0.049, -0.060, 0.046, 0.056, 0.050]\n });\n ambientCubemap.cubemap = graphicGL.loadTexture(textureUrl, api, {\n exposure: exposure\n }, function () {\n // TODO Performance when multiple view\n ambientCubemap.cubemap.flipY = false;\n\n if (process.env.NODE_ENV !== 'production') {\n var time = Date.now();\n }\n\n ambientCubemap.prefilter(renderer, 32);\n\n if (process.env.NODE_ENV !== 'production') {\n var dTime = Date.now() - time;\n console.log('Prefilter environment map: ' + dTime + 'ms');\n }\n\n ambientSH.coefficients = shUtil.projectEnvironmentMap(renderer, ambientCubemap.cubemap, {\n lod: 1\n });\n cb && cb(); // TODO Refresh ?\n });\n return {\n specular: ambientCubemap,\n diffuse: ambientSH\n };\n};\n/**\n * Create a blank texture for placeholder\n */\n\n\ngraphicGL.createBlankTexture = textureUtil.createBlank;\n/**\n * If value is image\n * @param {*}\n * @return {boolean}\n */\n\ngraphicGL.isImage = isValueImage;\n\ngraphicGL.additiveBlend = function (gl) {\n gl.blendEquation(gl.FUNC_ADD);\n gl.blendFunc(gl.SRC_ALPHA, gl.ONE);\n};\n/**\n * @param {string|Array.} colorStr\n * @param {Array.} [rgba]\n * @return {Array.} rgba\n */\n\n\ngraphicGL.parseColor = function (colorStr, rgba) {\n if (colorStr instanceof Array) {\n if (!rgba) {\n rgba = [];\n } // Color has been parsed.\n\n\n rgba[0] = colorStr[0];\n rgba[1] = colorStr[1];\n rgba[2] = colorStr[2];\n\n if (colorStr.length > 3) {\n rgba[3] = colorStr[3];\n } else {\n rgba[3] = 1;\n }\n\n return rgba;\n }\n\n rgba = echarts.color.parse(colorStr || '#000', rgba) || [0, 0, 0, 0];\n rgba[0] /= 255;\n rgba[1] /= 255;\n rgba[2] /= 255;\n return rgba;\n};\n/**\n * Convert alpha beta rotation to direction.\n * @param {number} alpha\n * @param {number} beta\n * @return {Array.}\n */\n\n\ngraphicGL.directionFromAlphaBeta = function (alpha, beta) {\n var theta = alpha / 180 * Math.PI + Math.PI / 2;\n var phi = -beta / 180 * Math.PI + Math.PI / 2;\n var dir = [];\n var r = Math.sin(theta);\n dir[0] = r * Math.cos(phi);\n dir[1] = -Math.cos(theta);\n dir[2] = r * Math.sin(phi);\n return dir;\n};\n/**\n * Get shadow resolution from shadowQuality configuration\n */\n\n\ngraphicGL.getShadowResolution = function (shadowQuality) {\n var shadowResolution = 1024;\n\n switch (shadowQuality) {\n case 'low':\n shadowResolution = 512;\n break;\n\n case 'medium':\n break;\n\n case 'high':\n shadowResolution = 2048;\n break;\n\n case 'ultra':\n shadowResolution = 4096;\n break;\n }\n\n return shadowResolution;\n};\n/**\n * Shading utilities\n */\n\n\ngraphicGL.COMMON_SHADERS = ['lambert', 'color', 'realistic', 'hatching', 'shadow'];\n/**\n * Create shader including vertex and fragment\n * @param {string} prefix.\n */\n\ngraphicGL.createShader = function (prefix) {\n if (prefix === 'ecgl.shadow') {\n prefix = 'ecgl.displayShadow';\n }\n\n var vertexShaderStr = Shader.source(prefix + '.vertex');\n var fragmentShaderStr = Shader.source(prefix + '.fragment');\n\n if (!vertexShaderStr) {\n console.error('Vertex shader of \\'%s\\' not exits', prefix);\n }\n\n if (!fragmentShaderStr) {\n console.error('Fragment shader of \\'%s\\' not exits', prefix);\n }\n\n var shader = new Shader(vertexShaderStr, fragmentShaderStr);\n shader.name = prefix;\n return shader;\n};\n\ngraphicGL.createMaterial = function (prefix, defines) {\n if (!(defines instanceof Array)) {\n defines = [defines];\n }\n\n var shader = graphicGL.createShader(prefix);\n var material = new Material({\n shader: shader\n });\n defines.forEach(function (defineName) {\n if (typeof defineName === 'string') {\n material.define(defineName);\n }\n });\n return material;\n};\n/**\n * Set material from model.\n * @param {clay.Material} material\n * @param {module:echarts/model/Model} model\n * @param {module:echarts/ExtensionAPI} api\n */\n\n\ngraphicGL.setMaterialFromModel = function (shading, material, model, api) {\n material.autoUpdateTextureStatus = false;\n var materialModel = model.getModel(shading + 'Material');\n var detailTexture = materialModel.get('detailTexture');\n var uvRepeat = retrieve.firstNotNull(materialModel.get('textureTiling'), 1.0);\n var uvOffset = retrieve.firstNotNull(materialModel.get('textureOffset'), 0.0);\n\n if (typeof uvRepeat === 'number') {\n uvRepeat = [uvRepeat, uvRepeat];\n }\n\n if (typeof uvOffset === 'number') {\n uvOffset = [uvOffset, uvOffset];\n }\n\n var repeatParam = uvRepeat[0] > 1 || uvRepeat[1] > 1 ? graphicGL.Texture.REPEAT : graphicGL.Texture.CLAMP_TO_EDGE;\n var textureOpt = {\n anisotropic: 8,\n wrapS: repeatParam,\n wrapT: repeatParam\n };\n\n if (shading === 'realistic') {\n var roughness = materialModel.get('roughness');\n var metalness = materialModel.get('metalness');\n\n if (metalness != null) {\n // Try to treat as a texture, TODO More check\n if (isNaN(metalness)) {\n material.setTextureImage('metalnessMap', metalness, api, textureOpt);\n metalness = retrieve.firstNotNull(materialModel.get('metalnessAdjust'), 0.5);\n }\n } else {\n // Default metalness.\n metalness = 0;\n }\n\n if (roughness != null) {\n // Try to treat as a texture, TODO More check\n if (isNaN(roughness)) {\n material.setTextureImage('roughnessMap', roughness, api, textureOpt);\n roughness = retrieve.firstNotNull(materialModel.get('roughnessAdjust'), 0.5);\n }\n } else {\n // Default roughness.\n roughness = 0.5;\n }\n\n var normalTextureVal = materialModel.get('normalTexture');\n material.setTextureImage('detailMap', detailTexture, api, textureOpt);\n material.setTextureImage('normalMap', normalTextureVal, api, textureOpt);\n material.set({\n roughness: roughness,\n metalness: metalness,\n detailUvRepeat: uvRepeat,\n detailUvOffset: uvOffset\n }); // var normalTexture = material.get('normalMap');\n // if (normalTexture) {\n // PENDING\n // normalTexture.format = Texture.SRGB;\n // }\n } else if (shading === 'lambert') {\n material.setTextureImage('detailMap', detailTexture, api, textureOpt);\n material.set({\n detailUvRepeat: uvRepeat,\n detailUvOffset: uvOffset\n });\n } else if (shading === 'color') {\n material.setTextureImage('detailMap', detailTexture, api, textureOpt);\n material.set({\n detailUvRepeat: uvRepeat,\n detailUvOffset: uvOffset\n });\n } else if (shading === 'hatching') {\n var tams = materialModel.get('hatchingTextures') || [];\n\n if (tams.length < 6) {\n if (process.env.NODE_ENV !== 'production') {\n console.error('Invalid hatchingTextures.');\n }\n }\n\n for (var i = 0; i < 6; i++) {\n material.setTextureImage('hatch' + (i + 1), tams[i], api, {\n anisotropic: 8,\n wrapS: graphicGL.Texture.REPEAT,\n wrapT: graphicGL.Texture.REPEAT\n });\n }\n\n material.set({\n detailUvRepeat: uvRepeat,\n detailUvOffset: uvOffset\n });\n }\n};\n\ngraphicGL.updateVertexAnimation = function (mappingAttributes, previousMesh, currentMesh, seriesModel) {\n var enableAnimation = seriesModel.get('animation');\n var duration = seriesModel.get('animationDurationUpdate');\n var easing = seriesModel.get('animationEasingUpdate');\n var shadowDepthMaterial = currentMesh.shadowDepthMaterial;\n\n if (enableAnimation && previousMesh && duration > 0 // Only animate when bar count are not changed\n && previousMesh.geometry.vertexCount === currentMesh.geometry.vertexCount) {\n currentMesh.material.define('vertex', 'VERTEX_ANIMATION');\n currentMesh.ignorePreZ = true;\n\n if (shadowDepthMaterial) {\n shadowDepthMaterial.define('vertex', 'VERTEX_ANIMATION');\n }\n\n for (var i = 0; i < mappingAttributes.length; i++) {\n currentMesh.geometry.attributes[mappingAttributes[i][0]].value = previousMesh.geometry.attributes[mappingAttributes[i][1]].value;\n }\n\n currentMesh.geometry.dirty();\n currentMesh.__percent = 0;\n currentMesh.material.set('percent', 0);\n currentMesh.stopAnimation();\n currentMesh.animate().when(duration, {\n __percent: 1\n }).during(function () {\n currentMesh.material.set('percent', currentMesh.__percent);\n\n if (shadowDepthMaterial) {\n shadowDepthMaterial.set('percent', currentMesh.__percent);\n }\n }).done(function () {\n currentMesh.ignorePreZ = false;\n currentMesh.material.undefine('vertex', 'VERTEX_ANIMATION');\n\n if (shadowDepthMaterial) {\n shadowDepthMaterial.undefine('vertex', 'VERTEX_ANIMATION');\n }\n }).start(easing);\n } else {\n currentMesh.material.undefine('vertex', 'VERTEX_ANIMATION');\n\n if (shadowDepthMaterial) {\n shadowDepthMaterial.undefine('vertex', 'VERTEX_ANIMATION');\n }\n }\n};\n\nexport default graphicGL;","/**\n * Provide WebGL layer to zrender. Which is rendered on top of clay.\n *\n *\n * Relationship between zrender, LayerGL(renderer) and ViewGL(Scene, Camera, Viewport)\n * zrender\n * / \\\n * LayerGL LayerGL\n * (renderer) (renderer)\n * / \\\n * ViewGL ViewGL\n */\nimport * as echarts from 'echarts/lib/echarts';\nimport Renderer from 'claygl/src/Renderer';\nimport RayPicking from 'claygl/src/picking/RayPicking';\nimport Texture from 'claygl/src/Texture';\nimport graphicGL from '../util/graphicGL'; // PENDING, clay. notifier is same with zrender Eventful\n\nimport notifier from 'claygl/src/core/mixin/notifier';\nimport requestAnimationFrame from 'zrender/lib/animation/requestAnimationFrame';\n/**\n * @constructor\n * @alias module:echarts-gl/core/LayerGL\n * @param {string} id Layer ID\n * @param {module:zrender/ZRender} zr\n */\n\nvar LayerGL = function (id, zr) {\n /**\n * Layer ID\n * @type {string}\n */\n this.id = id;\n /**\n * @type {module:zrender/ZRender}\n */\n\n this.zr = zr;\n /**\n * @type {clay.Renderer}\n */\n\n try {\n this.renderer = new Renderer({\n clearBit: 0,\n devicePixelRatio: zr.painter.dpr,\n preserveDrawingBuffer: true,\n // PENDING\n premultipliedAlpha: true\n });\n this.renderer.resize(zr.painter.getWidth(), zr.painter.getHeight());\n } catch (e) {\n this.renderer = null;\n this.dom = document.createElement('div');\n this.dom.style.cssText = 'position:absolute; left: 0; top: 0; right: 0; bottom: 0;';\n this.dom.className = 'ecgl-nowebgl';\n this.dom.innerHTML = 'Sorry, your browser does not support WebGL';\n console.error(e);\n return;\n }\n\n this.onglobalout = this.onglobalout.bind(this);\n zr.on('globalout', this.onglobalout);\n /**\n * Canvas dom for webgl rendering\n * @type {HTMLCanvasElement}\n */\n\n this.dom = this.renderer.canvas;\n var style = this.dom.style;\n style.position = 'absolute';\n style.left = '0';\n style.top = '0';\n /**\n * @type {Array.}\n */\n\n this.views = [];\n this._picking = new RayPicking({\n renderer: this.renderer\n });\n this._viewsToDispose = [];\n /**\n * Current accumulating id.\n */\n\n this._accumulatingId = 0;\n this._zrEventProxy = new echarts.graphic.Rect({\n shape: {\n x: -1,\n y: -1,\n width: 2,\n height: 2\n },\n // FIXME Better solution.\n __isGLToZRProxy: true\n });\n this._backgroundColor = null;\n this._disposed = false;\n};\n\nLayerGL.prototype.setUnpainted = function () {};\n/**\n * @param {module:echarts-gl/core/ViewGL} view\n */\n\n\nLayerGL.prototype.addView = function (view) {\n if (view.layer === this) {\n return;\n } // If needs to dispose in this layer. unmark it.\n\n\n var idx = this._viewsToDispose.indexOf(view);\n\n if (idx >= 0) {\n this._viewsToDispose.splice(idx, 1);\n }\n\n this.views.push(view);\n view.layer = this;\n var zr = this.zr;\n view.scene.traverse(function (node) {\n node.__zr = zr;\n\n if (node.addAnimatorsToZr) {\n node.addAnimatorsToZr(zr);\n }\n });\n};\n\nfunction removeFromZr(node) {\n var zr = node.__zr;\n node.__zr = null;\n\n if (zr && node.removeAnimatorsFromZr) {\n node.removeAnimatorsFromZr(zr);\n }\n}\n/**\n * @param {module:echarts-gl/core/ViewGL} view\n */\n\n\nLayerGL.prototype.removeView = function (view) {\n if (view.layer !== this) {\n return;\n }\n\n var idx = this.views.indexOf(view);\n\n if (idx >= 0) {\n this.views.splice(idx, 1);\n view.scene.traverse(removeFromZr, this);\n view.layer = null; // Mark to dispose in this layer.\n\n this._viewsToDispose.push(view);\n }\n};\n/**\n * Remove all views\n */\n\n\nLayerGL.prototype.removeViewsAll = function () {\n this.views.forEach(function (view) {\n view.scene.traverse(removeFromZr, this);\n view.layer = null; // Mark to dispose in this layer.\n\n this._viewsToDispose.push(view);\n }, this);\n this.views.length = 0;\n};\n/**\n * Resize the canvas and viewport, will be invoked by zrender\n * @param {number} width\n * @param {number} height\n */\n\n\nLayerGL.prototype.resize = function (width, height) {\n var renderer = this.renderer;\n renderer.resize(width, height);\n};\n/**\n * Clear color and depth\n * @return {[type]} [description]\n */\n\n\nLayerGL.prototype.clear = function () {\n var gl = this.renderer.gl;\n var clearColor = this._backgroundColor || [0, 0, 0, 0];\n gl.clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);\n gl.depthMask(true);\n gl.colorMask(true, true, true, true);\n gl.clear(gl.DEPTH_BUFFER_BIT | gl.COLOR_BUFFER_BIT);\n};\n/**\n * Clear depth\n */\n\n\nLayerGL.prototype.clearDepth = function () {\n var gl = this.renderer.gl;\n gl.clear(gl.DEPTH_BUFFER_BIT);\n};\n/**\n * Clear color\n */\n\n\nLayerGL.prototype.clearColor = function () {\n var gl = this.renderer.gl;\n gl.clearColor(0, 0, 0, 0);\n gl.clear(gl.COLOR_BUFFER_BIT);\n};\n/**\n * Mark layer to refresh next tick\n */\n\n\nLayerGL.prototype.needsRefresh = function () {\n this.zr.refresh();\n};\n/**\n * Refresh the layer, will be invoked by zrender\n */\n\n\nLayerGL.prototype.refresh = function (bgColor) {\n this._backgroundColor = bgColor ? graphicGL.parseColor(bgColor) : [0, 0, 0, 0];\n this.renderer.clearColor = this._backgroundColor;\n\n for (var i = 0; i < this.views.length; i++) {\n this.views[i].prepareRender(this.renderer);\n }\n\n this._doRender(false); // Auto dispose unused resources on GPU, like program(shader), texture, geometry(buffers)\n\n\n this._trackAndClean(); // Dispose trashed views\n\n\n for (var i = 0; i < this._viewsToDispose.length; i++) {\n this._viewsToDispose[i].dispose(this.renderer);\n }\n\n this._viewsToDispose.length = 0;\n\n this._startAccumulating();\n};\n\nLayerGL.prototype.renderToCanvas = function (ctx) {\n // PENDING will block the page\n this._startAccumulating(true);\n\n ctx.drawImage(this.dom, 0, 0, ctx.canvas.width, ctx.canvas.height);\n};\n\nLayerGL.prototype._doRender = function (accumulating) {\n this.clear();\n this.renderer.saveViewport();\n\n for (var i = 0; i < this.views.length; i++) {\n this.views[i].render(this.renderer, accumulating);\n }\n\n this.renderer.restoreViewport();\n};\n/**\n * Stop accumulating\n */\n\n\nLayerGL.prototype._stopAccumulating = function () {\n this._accumulatingId = 0;\n clearTimeout(this._accumulatingTimeout);\n};\n\nvar accumulatingId = 1;\n/**\n * Start accumulating all the views.\n * Accumulating is for antialising and have more sampling in SSAO\n * @private\n */\n\nLayerGL.prototype._startAccumulating = function (immediate) {\n var self = this;\n\n this._stopAccumulating();\n\n var needsAccumulate = false;\n\n for (var i = 0; i < this.views.length; i++) {\n needsAccumulate = this.views[i].needsAccumulate() || needsAccumulate;\n }\n\n if (!needsAccumulate) {\n return;\n }\n\n function accumulate(id) {\n if (!self._accumulatingId || id !== self._accumulatingId) {\n return;\n }\n\n var isFinished = true;\n\n for (var i = 0; i < self.views.length; i++) {\n isFinished = self.views[i].isAccumulateFinished() && needsAccumulate;\n }\n\n if (!isFinished) {\n self._doRender(true);\n\n if (immediate) {\n accumulate(id);\n } else {\n requestAnimationFrame(function () {\n accumulate(id);\n });\n }\n }\n }\n\n this._accumulatingId = accumulatingId++;\n\n if (immediate) {\n accumulate(self._accumulatingId);\n } else {\n this._accumulatingTimeout = setTimeout(function () {\n accumulate(self._accumulatingId);\n }, 50);\n }\n};\n\nLayerGL.prototype._trackAndClean = function () {\n var textureList = [];\n var geometriesList = []; // Mark all resources unused;\n\n if (this._textureList) {\n markUnused(this._textureList);\n markUnused(this._geometriesList);\n }\n\n for (var i = 0; i < this.views.length; i++) {\n collectResources(this.views[i].scene, textureList, geometriesList);\n } // Dispose those unsed resources.\n\n\n if (this._textureList) {\n checkAndDispose(this.renderer, this._textureList);\n checkAndDispose(this.renderer, this._geometriesList);\n }\n\n this._textureList = textureList;\n this._geometriesList = geometriesList;\n};\n\nfunction markUnused(resourceList) {\n for (var i = 0; i < resourceList.length; i++) {\n resourceList[i].__used__ = 0;\n }\n}\n\nfunction checkAndDispose(renderer, resourceList) {\n for (var i = 0; i < resourceList.length; i++) {\n if (!resourceList[i].__used__) {\n resourceList[i].dispose(renderer);\n }\n }\n}\n\nfunction updateUsed(resource, list) {\n resource.__used__ = resource.__used__ || 0;\n resource.__used__++;\n\n if (resource.__used__ === 1) {\n // Don't push to the list twice.\n list.push(resource);\n }\n}\n\nfunction collectResources(scene, textureResourceList, geometryResourceList) {\n var prevMaterial;\n var prevGeometry;\n scene.traverse(function (renderable) {\n if (renderable.isRenderable()) {\n var geometry = renderable.geometry;\n var material = renderable.material; // TODO optimize!!\n\n if (material !== prevMaterial) {\n var textureUniforms = material.getTextureUniforms();\n\n for (var u = 0; u < textureUniforms.length; u++) {\n var uniformName = textureUniforms[u];\n var val = material.uniforms[uniformName].value;\n\n if (!val) {\n continue;\n }\n\n if (val instanceof Texture) {\n updateUsed(val, textureResourceList);\n } else if (val instanceof Array) {\n for (var k = 0; k < val.length; k++) {\n if (val[k] instanceof Texture) {\n updateUsed(val[k], textureResourceList);\n }\n }\n }\n }\n }\n\n if (geometry !== prevGeometry) {\n updateUsed(geometry, geometryResourceList);\n }\n\n prevMaterial = material;\n prevGeometry = geometry;\n }\n });\n\n for (var k = 0; k < scene.lights.length; k++) {\n // Track AmbientCubemap\n if (scene.lights[k].cubemap) {\n updateUsed(scene.lights[k].cubemap, textureResourceList);\n }\n }\n}\n/**\n * Dispose the layer\n */\n\n\nLayerGL.prototype.dispose = function () {\n if (this._disposed) {\n return;\n }\n\n this._stopAccumulating();\n\n if (this._textureList) {\n markUnused(this._textureList);\n markUnused(this._geometriesList);\n checkAndDispose(this.renderer, this._textureList);\n checkAndDispose(this.renderer, this._geometriesList);\n }\n\n this.zr.off('globalout', this.onglobalout);\n this._disposed = true;\n}; // Event handlers\n\n\nLayerGL.prototype.onmousedown = function (e) {\n if (e.target && e.target.__isGLToZRProxy) {\n return;\n }\n\n e = e.event;\n var obj = this.pickObject(e.offsetX, e.offsetY);\n\n if (obj) {\n this._dispatchEvent('mousedown', e, obj);\n\n this._dispatchDataEvent('mousedown', e, obj);\n }\n\n this._downX = e.offsetX;\n this._downY = e.offsetY;\n};\n\nLayerGL.prototype.onmousemove = function (e) {\n if (e.target && e.target.__isGLToZRProxy) {\n return;\n }\n\n e = e.event;\n var obj = this.pickObject(e.offsetX, e.offsetY);\n var target = obj && obj.target;\n var lastHovered = this._hovered;\n this._hovered = obj;\n\n if (lastHovered && target !== lastHovered.target) {\n lastHovered.relatedTarget = target;\n\n this._dispatchEvent('mouseout', e, lastHovered); // this._dispatchDataEvent('mouseout', e, lastHovered);\n\n\n this.zr.setCursorStyle('default');\n }\n\n this._dispatchEvent('mousemove', e, obj);\n\n if (obj) {\n this.zr.setCursorStyle('pointer');\n\n if (!lastHovered || target !== lastHovered.target) {\n this._dispatchEvent('mouseover', e, obj); // this._dispatchDataEvent('mouseover', e, obj);\n\n }\n }\n\n this._dispatchDataEvent('mousemove', e, obj);\n};\n\nLayerGL.prototype.onmouseup = function (e) {\n if (e.target && e.target.__isGLToZRProxy) {\n return;\n }\n\n e = e.event;\n var obj = this.pickObject(e.offsetX, e.offsetY);\n\n if (obj) {\n this._dispatchEvent('mouseup', e, obj);\n\n this._dispatchDataEvent('mouseup', e, obj);\n }\n\n this._upX = e.offsetX;\n this._upY = e.offsetY;\n};\n\nLayerGL.prototype.onclick = LayerGL.prototype.dblclick = function (e) {\n if (e.target && e.target.__isGLToZRProxy) {\n return;\n } // Ignore click event if mouse moved\n\n\n var dx = this._upX - this._downX;\n var dy = this._upY - this._downY;\n\n if (Math.sqrt(dx * dx + dy * dy) > 20) {\n return;\n }\n\n e = e.event;\n var obj = this.pickObject(e.offsetX, e.offsetY);\n\n if (obj) {\n this._dispatchEvent(e.type, e, obj);\n\n this._dispatchDataEvent(e.type, e, obj);\n } // Try set depth of field onclick\n\n\n var result = this._clickToSetFocusPoint(e);\n\n if (result) {\n var success = result.view.setDOFFocusOnPoint(result.distance);\n\n if (success) {\n this.zr.refresh();\n }\n }\n};\n\nLayerGL.prototype._clickToSetFocusPoint = function (e) {\n var renderer = this.renderer;\n var oldViewport = renderer.viewport;\n\n for (var i = this.views.length - 1; i >= 0; i--) {\n var viewGL = this.views[i];\n\n if (viewGL.hasDOF() && viewGL.containPoint(e.offsetX, e.offsetY)) {\n this._picking.scene = viewGL.scene;\n this._picking.camera = viewGL.camera; // Only used for picking, renderer.setViewport will also invoke gl.viewport.\n // Set directly, PENDING.\n\n renderer.viewport = viewGL.viewport;\n\n var result = this._picking.pick(e.offsetX, e.offsetY, true);\n\n if (result) {\n result.view = viewGL;\n return result;\n }\n }\n }\n\n renderer.viewport = oldViewport;\n};\n\nLayerGL.prototype.onglobalout = function (e) {\n var lastHovered = this._hovered;\n\n if (lastHovered) {\n this._dispatchEvent('mouseout', e, {\n target: lastHovered.target\n });\n }\n};\n\nLayerGL.prototype.pickObject = function (x, y) {\n var output = [];\n var renderer = this.renderer;\n var oldViewport = renderer.viewport;\n\n for (var i = 0; i < this.views.length; i++) {\n var viewGL = this.views[i];\n\n if (viewGL.containPoint(x, y)) {\n this._picking.scene = viewGL.scene;\n this._picking.camera = viewGL.camera; // Only used for picking, renderer.setViewport will also invoke gl.viewport.\n // Set directly, PENDING.\n\n renderer.viewport = viewGL.viewport;\n\n this._picking.pickAll(x, y, output);\n }\n }\n\n renderer.viewport = oldViewport;\n output.sort(function (a, b) {\n return a.distance - b.distance;\n });\n return output[0];\n};\n\nLayerGL.prototype._dispatchEvent = function (eveName, originalEvent, newEvent) {\n if (!newEvent) {\n newEvent = {};\n }\n\n var current = newEvent.target;\n newEvent.cancelBubble = false;\n newEvent.event = originalEvent;\n newEvent.type = eveName;\n newEvent.offsetX = originalEvent.offsetX;\n newEvent.offsetY = originalEvent.offsetY;\n\n while (current) {\n current.trigger(eveName, newEvent);\n current = current.getParent();\n\n if (newEvent.cancelBubble) {\n break;\n }\n }\n\n this._dispatchToView(eveName, newEvent);\n};\n\nLayerGL.prototype._dispatchDataEvent = function (eveName, originalEvent, newEvent) {\n var mesh = newEvent && newEvent.target;\n var dataIndex = mesh && mesh.dataIndex;\n var seriesIndex = mesh && mesh.seriesIndex; // Custom event data\n\n var eventData = mesh && mesh.eventData;\n var elChangedInMouseMove = false;\n var eventProxy = this._zrEventProxy;\n eventProxy.x = originalEvent.offsetX;\n eventProxy.y = originalEvent.offsetY;\n eventProxy.update();\n var targetInfo = {\n target: eventProxy\n };\n const ecData = echarts.helper.getECData(eventProxy);\n\n if (eveName === 'mousemove') {\n if (dataIndex != null) {\n if (dataIndex !== this._lastDataIndex) {\n if (parseInt(this._lastDataIndex, 10) >= 0) {\n ecData.dataIndex = this._lastDataIndex;\n ecData.seriesIndex = this._lastSeriesIndex; // FIXME May cause double events.\n\n this.zr.handler.dispatchToElement(targetInfo, 'mouseout', originalEvent);\n }\n\n elChangedInMouseMove = true;\n }\n } else if (eventData != null) {\n if (eventData !== this._lastEventData) {\n if (this._lastEventData != null) {\n ecData.eventData = this._lastEventData; // FIXME May cause double events.\n\n this.zr.handler.dispatchToElement(targetInfo, 'mouseout', originalEvent);\n }\n\n elChangedInMouseMove = true;\n }\n }\n\n this._lastEventData = eventData;\n this._lastDataIndex = dataIndex;\n this._lastSeriesIndex = seriesIndex;\n }\n\n ecData.eventData = eventData;\n ecData.dataIndex = dataIndex;\n ecData.seriesIndex = seriesIndex;\n\n if (eventData != null || parseInt(dataIndex, 10) >= 0 && parseInt(seriesIndex, 10) >= 0) {\n this.zr.handler.dispatchToElement(targetInfo, eveName, originalEvent);\n\n if (elChangedInMouseMove) {\n this.zr.handler.dispatchToElement(targetInfo, 'mouseover', originalEvent);\n }\n }\n};\n\nLayerGL.prototype._dispatchToView = function (eventName, e) {\n for (var i = 0; i < this.views.length; i++) {\n if (this.views[i].containPoint(e.offsetX, e.offsetY)) {\n this.views[i].trigger(eventName, e);\n }\n }\n};\n\nObject.assign(LayerGL.prototype, notifier);\nexport default LayerGL;","import * as echarts from 'echarts/lib/echarts';\nvar GL_SERIES = ['bar3D', 'line3D', 'map3D', 'scatter3D', 'surface', 'lines3D', 'scatterGL', 'scatter3D'];\n\nfunction convertNormalEmphasis(option, optType) {\n if (option && option[optType] && (option[optType].normal || option[optType].emphasis)) {\n var normalOpt = option[optType].normal;\n var emphasisOpt = option[optType].emphasis;\n\n if (normalOpt) {\n option[optType] = normalOpt;\n }\n\n if (emphasisOpt) {\n option.emphasis = option.emphasis || {};\n option.emphasis[optType] = emphasisOpt;\n }\n }\n}\n\nfunction convertNormalEmphasisForEach(option) {\n convertNormalEmphasis(option, 'itemStyle');\n convertNormalEmphasis(option, 'lineStyle');\n convertNormalEmphasis(option, 'areaStyle');\n convertNormalEmphasis(option, 'label');\n}\n\nfunction removeTextStyleInAxis(axesOpt) {\n if (!axesOpt) {\n return;\n }\n\n if (!(axesOpt instanceof Array)) {\n axesOpt = [axesOpt];\n }\n\n echarts.util.each(axesOpt, function (axisOpt) {\n if (axisOpt.axisLabel) {\n var labelOpt = axisOpt.axisLabel;\n Object.assign(labelOpt, labelOpt.textStyle);\n labelOpt.textStyle = null;\n }\n });\n}\n\nexport default function (option) {\n echarts.util.each(option.series, function (series) {\n if (echarts.util.indexOf(GL_SERIES, series.type) >= 0) {\n convertNormalEmphasisForEach(series); // Compatitable with original mapbox\n\n if (series.coordinateSystem === 'mapbox') {\n series.coordinateSystem = 'mapbox3D';\n option.mapbox3D = option.mapbox;\n }\n }\n });\n removeTextStyleInAxis(option.xAxis3D);\n removeTextStyleInAxis(option.yAxis3D);\n removeTextStyleInAxis(option.zAxis3D);\n removeTextStyleInAxis(option.grid3D);\n convertNormalEmphasis(option.geo3D);\n}\n;","/**\n * echarts-gl\n * Extension pack of ECharts providing 3d plots and globe visualization\n *\n * Copyright (c) 2014, echarts-gl\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n * * Redistributions of source code must retain the above copyright notice, this\n * list of conditions and the following disclaimer.\n *\n * * Redistributions in binary form must reproduce the above copyright notice,\n * this list of conditions and the following disclaimer in the documentation\n * and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\nimport * as echarts from 'echarts/lib/echarts';\nimport LayerGL from './core/LayerGL';\nimport backwardCompat from './preprocessor/backwardCompat';\n\nfunction EChartsGL(zr) {\n this._layers = {};\n this._zr = zr;\n}\n\nEChartsGL.prototype.update = function (ecModel, api) {\n var self = this;\n var zr = api.getZr();\n\n if (!zr.getWidth() || !zr.getHeight()) {\n console.warn('Dom has no width or height');\n return;\n }\n\n function getLayerGL(model) {\n // Disable auto sleep in gl layer.\n zr.setSleepAfterStill(0);\n var zlevel; // Host on coordinate system.\n\n if (model.coordinateSystem && model.coordinateSystem.model) {\n zlevel = model.get('zlevel');\n } else {\n zlevel = model.get('zlevel');\n }\n\n var layers = self._layers;\n var layerGL = layers[zlevel];\n\n if (!layerGL) {\n layerGL = layers[zlevel] = new LayerGL('gl-' + zlevel, zr);\n\n if (zr.painter.isSingleCanvas()) {\n layerGL.virtual = true; // If container is canvas, use image to represent LayerGL\n // FIXME Performance\n\n var img = new echarts.graphic.Image({\n z: 1e4,\n style: {\n image: layerGL.renderer.canvas\n },\n silent: true\n });\n layerGL.__hostImage = img;\n zr.add(img);\n }\n\n zr.painter.insertLayer(zlevel, layerGL);\n }\n\n if (layerGL.__hostImage) {\n layerGL.__hostImage.setStyle({\n width: layerGL.renderer.getWidth(),\n height: layerGL.renderer.getHeight()\n });\n }\n\n return layerGL;\n }\n\n function setSilent(groupGL, silent) {\n if (groupGL) {\n groupGL.traverse(function (mesh) {\n if (mesh.isRenderable && mesh.isRenderable()) {\n mesh.ignorePicking = mesh.$ignorePicking != null ? mesh.$ignorePicking : silent;\n }\n });\n }\n }\n\n for (var zlevel in this._layers) {\n this._layers[zlevel].removeViewsAll();\n }\n\n ecModel.eachComponent(function (componentType, componentModel) {\n if (componentType !== 'series') {\n var view = api.getViewOfComponentModel(componentModel);\n var coordSys = componentModel.coordinateSystem; // View with __ecgl__ flag is a echarts-gl component.\n\n if (view.__ecgl__) {\n var viewGL;\n\n if (coordSys) {\n if (!coordSys.viewGL) {\n console.error('Can\\'t find viewGL in coordinateSystem of component ' + componentModel.id);\n return;\n }\n\n viewGL = coordSys.viewGL;\n } else {\n if (!componentModel.viewGL) {\n console.error('Can\\'t find viewGL of component ' + componentModel.id);\n return;\n }\n\n viewGL = coordSys.viewGL;\n }\n\n var viewGL = coordSys.viewGL;\n var layerGL = getLayerGL(componentModel);\n layerGL.addView(viewGL);\n view.afterRender && view.afterRender(componentModel, ecModel, api, layerGL);\n setSilent(view.groupGL, componentModel.get('silent'));\n }\n }\n });\n ecModel.eachSeries(function (seriesModel) {\n var chartView = api.getViewOfSeriesModel(seriesModel);\n var coordSys = seriesModel.coordinateSystem;\n\n if (chartView.__ecgl__) {\n if (coordSys && !coordSys.viewGL && !chartView.viewGL) {\n console.error('Can\\'t find viewGL of series ' + chartView.id);\n return;\n }\n\n var viewGL = coordSys && coordSys.viewGL || chartView.viewGL; // TODO Check zlevel not same with component of coordinate system ?\n\n var layerGL = getLayerGL(seriesModel);\n layerGL.addView(viewGL);\n chartView.afterRender && chartView.afterRender(seriesModel, ecModel, api, layerGL);\n setSilent(chartView.groupGL, seriesModel.get('silent'));\n }\n });\n}; // Hack original getRenderedCanvas. Will removed after new echarts released\n// TODO\n\n\necharts.registerPostInit(function (chart) {\n var zr = chart.getZr();\n var oldDispose = zr.painter.dispose;\n\n zr.painter.dispose = function () {\n if (typeof this.eachOtherLayer === 'function') {\n this.eachOtherLayer(function (layer) {\n if (layer instanceof LayerGL) {\n layer.dispose();\n }\n });\n }\n\n oldDispose.call(this);\n };\n\n zr.painter.getRenderedCanvas = function (opts) {\n opts = opts || {};\n\n if (this._singleCanvas) {\n return this._layers[0].dom;\n }\n\n var canvas = document.createElement('canvas');\n var dpr = opts.pixelRatio || this.dpr;\n canvas.width = this.getWidth() * dpr;\n canvas.height = this.getHeight() * dpr;\n var ctx = canvas.getContext('2d');\n ctx.dpr = dpr;\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n\n if (opts.backgroundColor) {\n ctx.fillStyle = opts.backgroundColor;\n ctx.fillRect(0, 0, canvas.width, canvas.height);\n }\n\n var displayList = this.storage.getDisplayList(true);\n var scope = {};\n var zlevel;\n var self = this;\n\n function findAndDrawOtherLayer(smaller, larger) {\n var zlevelList = self._zlevelList;\n\n if (smaller == null) {\n smaller = -Infinity;\n }\n\n var intermediateLayer;\n\n for (var i = 0; i < zlevelList.length; i++) {\n var z = zlevelList[i];\n var layer = self._layers[z];\n\n if (!layer.__builtin__ && z > smaller && z < larger) {\n intermediateLayer = layer;\n break;\n }\n }\n\n if (intermediateLayer && intermediateLayer.renderToCanvas) {\n ctx.save();\n intermediateLayer.renderToCanvas(ctx);\n ctx.restore();\n }\n }\n\n var layer = {\n ctx: ctx\n };\n\n for (var i = 0; i < displayList.length; i++) {\n var el = displayList[i];\n\n if (el.zlevel !== zlevel) {\n findAndDrawOtherLayer(zlevel, el.zlevel);\n zlevel = el.zlevel;\n }\n\n this._doPaintEl(el, layer, true, null, scope);\n }\n\n findAndDrawOtherLayer(zlevel, Infinity);\n return canvas;\n };\n});\necharts.registerPostUpdate(function (ecModel, api) {\n var zr = api.getZr();\n var egl = zr.__egl = zr.__egl || new EChartsGL(zr);\n egl.update(ecModel, api);\n});\necharts.registerPreprocessor(backwardCompat);\nexport default EChartsGL;","export default {\n defaultOption: {\n viewControl: {\n // perspective, orthographic.\n // TODO Isometric\n projection: 'perspective',\n // If rotate on on init\n autoRotate: false,\n // cw or ccw\n autoRotateDirection: 'cw',\n // Degree per second\n autoRotateSpeed: 10,\n // Start rotating after still for a given time\n // default is 3 seconds\n autoRotateAfterStill: 3,\n // Rotate, zoom damping.\n damping: 0.8,\n // Sensitivities for operations.\n // Can be array to set x,y respectively\n rotateSensitivity: 1,\n zoomSensitivity: 1,\n // Can be array to set x,y respectively\n panSensitivity: 1,\n // Which mouse button do rotate or pan\n panMouseButton: 'middle',\n rotateMouseButton: 'left',\n // Distance to the target\n // Only available when camera is perspective.\n distance: 150,\n // Min distance mouse can zoom in\n minDistance: 40,\n // Max distance mouse can zoom out\n maxDistance: 400,\n // Size of viewing volume.\n // Only available when camera is orthographic\n orthographicSize: 150,\n maxOrthographicSize: 400,\n minOrthographicSize: 20,\n // Center view point\n center: [0, 0, 0],\n // Alpha angle for top-down rotation\n // Positive to rotate to top.\n alpha: 0,\n // beta angle for left-right rotation\n // Positive to rotate to right.\n beta: 0,\n minAlpha: -90,\n maxAlpha: 90 // minBeta: -Infinity\n // maxBeta: -Infinity\n\n }\n },\n setView: function (opts) {\n opts = opts || {};\n this.option.viewControl = this.option.viewControl || {};\n\n if (opts.alpha != null) {\n this.option.viewControl.alpha = opts.alpha;\n }\n\n if (opts.beta != null) {\n this.option.viewControl.beta = opts.beta;\n }\n\n if (opts.distance != null) {\n this.option.viewControl.distance = opts.distance;\n }\n\n if (opts.center != null) {\n this.option.viewControl.center = opts.center;\n }\n }\n};","export default {\n defaultOption: {\n // Post effect\n postEffect: {\n enable: false,\n bloom: {\n enable: true,\n intensity: 0.1\n },\n depthOfField: {\n enable: false,\n focalRange: 20,\n focalDistance: 50,\n blurRadius: 10,\n fstop: 2.8,\n quality: 'medium'\n },\n screenSpaceAmbientOcclusion: {\n enable: false,\n radius: 2,\n // low, medium, high, ultra\n quality: 'medium',\n intensity: 1\n },\n screenSpaceReflection: {\n enable: false,\n quality: 'medium',\n maxRoughness: 0.8\n },\n colorCorrection: {\n enable: true,\n exposure: 0,\n brightness: 0,\n contrast: 1,\n saturation: 1,\n lookupTexture: ''\n },\n edge: {\n enable: false\n },\n FXAA: {\n enable: false\n }\n },\n // Temporal super sampling when the picture is still.\n temporalSuperSampling: {\n // Only enabled when postEffect is enabled\n enable: 'auto'\n }\n }\n};","export default {\n defaultOption: {\n // Light is available when material.shading is not color\n light: {\n // Main light\n main: {\n shadow: false,\n // low, medium, high, ultra\n shadowQuality: 'high',\n color: '#fff',\n intensity: 1,\n alpha: 0,\n beta: 0\n },\n ambient: {\n color: '#fff',\n intensity: 0.2\n },\n ambientCubemap: {\n // Panorama environment texture,\n // Support .hdr and commmon web formats.\n texture: null,\n // Available when texture is hdr.\n exposure: 1,\n // Intensity for diffuse term\n diffuseIntensity: 0.5,\n // Intensity for specular term, only available when shading is realastic\n specularIntensity: 0.5\n }\n }\n }\n};","import * as echarts from 'echarts/lib/echarts';\nimport componentViewControlMixin from '../common/componentViewControlMixin';\nimport componentPostEffectMixin from '../common/componentPostEffectMixin';\nimport componentLightMixin from '../common/componentLightMixin';\nvar Grid3DModel = echarts.ComponentModel.extend({\n type: 'grid3D',\n dependencies: ['xAxis3D', 'yAxis3D', 'zAxis3D'],\n defaultOption: {\n show: true,\n zlevel: -10,\n // Layout used for viewport\n left: 0,\n top: 0,\n width: '100%',\n height: '100%',\n environment: 'auto',\n // Dimension of grid3D\n boxWidth: 100,\n boxHeight: 100,\n boxDepth: 100,\n // Common axis options.\n axisPointer: {\n show: true,\n lineStyle: {\n color: 'rgba(0, 0, 0, 0.8)',\n width: 1\n },\n label: {\n show: true,\n // (dimValue: number, value: Array) => string\n formatter: null,\n // TODO, Consider boxWidth\n margin: 8,\n // backgroundColor: '#ffbd67',\n // borderColor: '#000',\n // borderWidth: 0,\n textStyle: {\n fontSize: 14,\n color: '#fff',\n backgroundColor: 'rgba(0,0,0,0.5)',\n padding: 3,\n borderRadius: 3\n }\n }\n },\n axisLine: {\n show: true,\n lineStyle: {\n color: '#333',\n width: 2,\n type: 'solid'\n }\n },\n axisTick: {\n show: true,\n inside: false,\n length: 3,\n lineStyle: {\n width: 1\n }\n },\n axisLabel: {\n show: true,\n inside: false,\n rotate: 0,\n margin: 8,\n textStyle: {\n fontSize: 12\n }\n },\n splitLine: {\n show: true,\n lineStyle: {\n color: ['#ccc'],\n width: 1,\n type: 'solid'\n }\n },\n splitArea: {\n show: false,\n areaStyle: {\n color: ['rgba(250,250,250,0.3)', 'rgba(200,200,200,0.3)']\n }\n },\n // Light options\n light: {\n main: {\n // Alpha angle for top-down rotation\n // Positive to rotate to top.\n alpha: 30,\n // beta angle for left-right rotation\n // Positive to rotate to right.\n beta: 40\n },\n ambient: {\n intensity: 0.4\n }\n },\n viewControl: {\n // Small damping for precise control.\n // damping: 0.1,\n // Alpha angle for top-down rotation\n // Positive to rotate to top.\n alpha: 20,\n // beta angle for left-right rotation\n // Positive to rotate to right.\n beta: 40,\n autoRotate: false,\n // Distance to the surface of grid3D.\n distance: 200,\n // Min distance to the surface of grid3D\n minDistance: 40,\n // Max distance to the surface of grid3D\n maxDistance: 400\n }\n }\n});\necharts.util.merge(Grid3DModel.prototype, componentViewControlMixin);\necharts.util.merge(Grid3DModel.prototype, componentPostEffectMixin);\necharts.util.merge(Grid3DModel.prototype, componentLightMixin);\nexport default Grid3DModel;","/**\n * Provide orbit control for 3D objects\n *\n * @module echarts-gl/util/OrbitControl\n * @author Yi Shen(http://github.com/pissang)\n */\n// TODO Remove magic numbers on sensitivity\nimport Base from 'claygl/src/core/Base';\nimport Vector2 from 'claygl/src/math/Vector2';\nimport Vector3 from 'claygl/src/math/Vector3';\nimport Quaternion from 'claygl/src/math/Quaternion';\nimport retrieve from './retrieve';\nvar firstNotNull = retrieve.firstNotNull;\nvar MOUSE_BUTTON_KEY_MAP = {\n left: 0,\n middle: 1,\n right: 2\n};\n\nfunction convertToArray(val) {\n if (!(val instanceof Array)) {\n val = [val, val];\n }\n\n return val;\n}\n/**\n * @alias module:echarts-x/util/OrbitControl\n */\n\n\nvar OrbitControl = Base.extend(function () {\n return {\n /**\n * @type {module:zrender~ZRender}\n */\n zr: null,\n\n /**\n * @type {module:echarts-gl/core/ViewGL}\n */\n viewGL: null,\n\n /**\n * @type {clay.math.Vector3}\n */\n _center: new Vector3(),\n\n /**\n * Minimum distance to the center\n * Only available when camera is perspective.\n * @type {number}\n * @default 0.5\n */\n minDistance: 0.5,\n\n /**\n * Maximum distance to the center\n * Only available when camera is perspective.\n * @type {number}\n * @default 2\n */\n maxDistance: 1.5,\n\n /**\n * Only available when camera is orthographic\n */\n maxOrthographicSize: 300,\n\n /**\n * Only available when camera is orthographic\n */\n minOrthographicSize: 30,\n\n /**\n * Minimum alpha rotation\n */\n minAlpha: -90,\n\n /**\n * Maximum alpha rotation\n */\n maxAlpha: 90,\n\n /**\n * Minimum beta rotation\n */\n minBeta: -Infinity,\n\n /**\n * Maximum beta rotation\n */\n maxBeta: Infinity,\n\n /**\n * Start auto rotating after still for the given time\n */\n autoRotateAfterStill: 0,\n\n /**\n * Direction of autoRotate. cw or ccw when looking top down.\n */\n autoRotateDirection: 'cw',\n\n /**\n * Degree per second\n */\n autoRotateSpeed: 60,\n\n /**\n * @param {number}\n */\n damping: 0.8,\n\n /**\n * @param {number}\n */\n rotateSensitivity: 1,\n\n /**\n * @param {number}\n */\n zoomSensitivity: 1,\n\n /**\n * @param {number}\n */\n panSensitivity: 1,\n panMouseButton: 'middle',\n rotateMouseButton: 'left',\n\n /**\n * Pan or rotate\n * @private\n * @type {String}\n */\n _mode: 'rotate',\n\n /**\n * @private\n * @type {clay.Camera}\n */\n _camera: null,\n _needsUpdate: false,\n _rotating: false,\n // Rotation around yAxis in radian\n _phi: 0,\n // Rotation around xAxis in radian\n _theta: 0,\n _mouseX: 0,\n _mouseY: 0,\n _rotateVelocity: new Vector2(),\n _panVelocity: new Vector2(),\n _distance: 500,\n _zoomSpeed: 0,\n _stillTimeout: 0,\n _animators: []\n };\n}, function () {\n // Each OrbitControl has it's own handler\n ['_mouseDownHandler', '_mouseWheelHandler', '_mouseMoveHandler', '_mouseUpHandler', '_pinchHandler', '_contextMenuHandler', '_update'].forEach(function (hdlName) {\n this[hdlName] = this[hdlName].bind(this);\n }, this);\n}, {\n /**\n * Initialize.\n * Mouse event binding\n */\n init: function () {\n var zr = this.zr;\n\n if (zr) {\n zr.on('mousedown', this._mouseDownHandler);\n zr.on('globalout', this._mouseUpHandler);\n zr.on('mousewheel', this._mouseWheelHandler);\n zr.on('pinch', this._pinchHandler);\n zr.animation.on('frame', this._update);\n zr.dom.addEventListener('contextmenu', this._contextMenuHandler);\n }\n },\n\n /**\n * Dispose.\n * Mouse event unbinding\n */\n dispose: function () {\n var zr = this.zr;\n\n if (zr) {\n zr.off('mousedown', this._mouseDownHandler);\n zr.off('mousemove', this._mouseMoveHandler);\n zr.off('mouseup', this._mouseUpHandler);\n zr.off('mousewheel', this._mouseWheelHandler);\n zr.off('pinch', this._pinchHandler);\n zr.off('globalout', this._mouseUpHandler);\n zr.dom.removeEventListener('contextmenu', this._contextMenuHandler);\n zr.animation.off('frame', this._update);\n }\n\n this.stopAllAnimation();\n },\n\n /**\n * Get distance\n * @return {number}\n */\n getDistance: function () {\n return this._distance;\n },\n\n /**\n * Set distance\n * @param {number} distance\n */\n setDistance: function (distance) {\n this._distance = distance;\n this._needsUpdate = true;\n },\n\n /**\n * Get size of orthographic viewing volume\n * @return {number}\n */\n getOrthographicSize: function () {\n return this._orthoSize;\n },\n\n /**\n * Set size of orthographic viewing volume\n * @param {number} size\n */\n setOrthographicSize: function (size) {\n this._orthoSize = size;\n this._needsUpdate = true;\n },\n\n /**\n * Get alpha rotation\n * Alpha angle for top-down rotation. Positive to rotate to top.\n *\n * Which means camera rotation around x axis.\n */\n getAlpha: function () {\n return this._theta / Math.PI * 180;\n },\n\n /**\n * Get beta rotation\n * Beta angle for left-right rotation. Positive to rotate to right.\n *\n * Which means camera rotation around y axis.\n */\n getBeta: function () {\n return -this._phi / Math.PI * 180;\n },\n\n /**\n * Get control center\n * @return {Array.}\n */\n getCenter: function () {\n return this._center.toArray();\n },\n\n /**\n * Set alpha rotation angle\n * @param {number} alpha\n */\n setAlpha: function (alpha) {\n alpha = Math.max(Math.min(this.maxAlpha, alpha), this.minAlpha);\n this._theta = alpha / 180 * Math.PI;\n this._needsUpdate = true;\n },\n\n /**\n * Set beta rotation angle\n * @param {number} beta\n */\n setBeta: function (beta) {\n beta = Math.max(Math.min(this.maxBeta, beta), this.minBeta);\n this._phi = -beta / 180 * Math.PI;\n this._needsUpdate = true;\n },\n\n /**\n * Set control center\n * @param {Array.} center\n */\n setCenter: function (centerArr) {\n this._center.setArray(centerArr);\n },\n\n /**\n * @param {module:echarts-gl/core/ViewGL} viewGL\n */\n setViewGL: function (viewGL) {\n this.viewGL = viewGL;\n },\n\n /**\n * @return {clay.Camera}\n */\n getCamera: function () {\n return this.viewGL.camera;\n },\n setFromViewControlModel: function (viewControlModel, extraOpts) {\n extraOpts = extraOpts || {};\n var baseDistance = extraOpts.baseDistance || 0;\n var baseOrthoSize = extraOpts.baseOrthoSize || 1;\n var projection = viewControlModel.get('projection');\n\n if (projection !== 'perspective' && projection !== 'orthographic' && projection !== 'isometric') {\n if (process.env.NODE_ENV !== 'production') {\n console.error('Unkown projection type %s, use perspective projection instead.', projection);\n }\n\n projection = 'perspective';\n }\n\n this._projection = projection;\n this.viewGL.setProjection(projection);\n var targetDistance = viewControlModel.get('distance') + baseDistance;\n var targetOrthographicSize = viewControlModel.get('orthographicSize') + baseOrthoSize;\n [['damping', 0.8], ['autoRotate', false], ['autoRotateAfterStill', 3], ['autoRotateDirection', 'cw'], ['autoRotateSpeed', 10], ['minDistance', 30], ['maxDistance', 400], ['minOrthographicSize', 30], ['maxOrthographicSize', 300], ['minAlpha', -90], ['maxAlpha', 90], ['minBeta', -Infinity], ['maxBeta', Infinity], ['rotateSensitivity', 1], ['zoomSensitivity', 1], ['panSensitivity', 1], ['panMouseButton', 'left'], ['rotateMouseButton', 'middle']].forEach(function (prop) {\n this[prop[0]] = firstNotNull(viewControlModel.get(prop[0]), prop[1]);\n }, this);\n this.minDistance += baseDistance;\n this.maxDistance += baseDistance;\n this.minOrthographicSize += baseOrthoSize, this.maxOrthographicSize += baseOrthoSize;\n var ecModel = viewControlModel.ecModel;\n var animationOpts = {};\n ['animation', 'animationDurationUpdate', 'animationEasingUpdate'].forEach(function (key) {\n animationOpts[key] = firstNotNull(viewControlModel.get(key), ecModel && ecModel.get(key));\n });\n var alpha = firstNotNull(extraOpts.alpha, viewControlModel.get('alpha')) || 0;\n var beta = firstNotNull(extraOpts.beta, viewControlModel.get('beta')) || 0;\n var center = firstNotNull(extraOpts.center, viewControlModel.get('center')) || [0, 0, 0];\n\n if (animationOpts.animation && animationOpts.animationDurationUpdate > 0 && this._notFirst) {\n this.animateTo({\n alpha: alpha,\n beta: beta,\n center: center,\n distance: targetDistance,\n orthographicSize: targetOrthographicSize,\n easing: animationOpts.animationEasingUpdate,\n duration: animationOpts.animationDurationUpdate\n });\n } else {\n this.setDistance(targetDistance);\n this.setAlpha(alpha);\n this.setBeta(beta);\n this.setCenter(center);\n this.setOrthographicSize(targetOrthographicSize);\n }\n\n this._notFirst = true;\n\n this._validateProperties();\n },\n _validateProperties: function () {\n if (process.env.NODE_ENV !== 'production') {\n if (MOUSE_BUTTON_KEY_MAP[this.panMouseButton] == null) {\n console.error('Unkown panMouseButton %s. It should be left|middle|right', this.panMouseButton);\n }\n\n if (MOUSE_BUTTON_KEY_MAP[this.rotateMouseButton] == null) {\n console.error('Unkown rotateMouseButton %s. It should be left|middle|right', this.rotateMouseButton);\n }\n\n if (this.autoRotateDirection !== 'cw' && this.autoRotateDirection !== 'ccw') {\n console.error('Unkown autoRotateDirection %s. It should be cw|ccw', this.autoRotateDirection);\n }\n }\n },\n\n /**\n * @param {Object} opts\n * @param {number} opts.distance\n * @param {number} opts.alpha\n * @param {number} opts.beta\n * @param {number} opts.orthographicSize\n * @param {number} [opts.duration=1000]\n * @param {number} [opts.easing='linear']\n */\n animateTo: function (opts) {\n var zr = this.zr;\n var self = this;\n var obj = {};\n var target = {};\n\n if (opts.distance != null) {\n obj.distance = this.getDistance();\n target.distance = opts.distance;\n }\n\n if (opts.orthographicSize != null) {\n obj.orthographicSize = this.getOrthographicSize();\n target.orthographicSize = opts.orthographicSize;\n }\n\n if (opts.alpha != null) {\n obj.alpha = this.getAlpha();\n target.alpha = opts.alpha;\n }\n\n if (opts.beta != null) {\n obj.beta = this.getBeta();\n target.beta = opts.beta;\n }\n\n if (opts.center != null) {\n obj.center = this.getCenter();\n target.center = opts.center;\n }\n\n return this._addAnimator(zr.animation.animate(obj).when(opts.duration || 1000, target).during(function () {\n if (obj.alpha != null) {\n self.setAlpha(obj.alpha);\n }\n\n if (obj.beta != null) {\n self.setBeta(obj.beta);\n }\n\n if (obj.distance != null) {\n self.setDistance(obj.distance);\n }\n\n if (obj.center != null) {\n self.setCenter(obj.center);\n }\n\n if (obj.orthographicSize != null) {\n self.setOrthographicSize(obj.orthographicSize);\n }\n\n self._needsUpdate = true;\n })).start(opts.easing || 'linear');\n },\n\n /**\n * Stop all animation\n */\n stopAllAnimation: function () {\n for (var i = 0; i < this._animators.length; i++) {\n this._animators[i].stop();\n }\n\n this._animators.length = 0;\n },\n update: function () {\n this._needsUpdate = true;\n\n this._update(20);\n },\n _isAnimating: function () {\n return this._animators.length > 0;\n },\n\n /**\n * Call update each frame\n * @param {number} deltaTime Frame time\n */\n _update: function (deltaTime) {\n if (this._rotating) {\n var radian = (this.autoRotateDirection === 'cw' ? 1 : -1) * this.autoRotateSpeed / 180 * Math.PI;\n this._phi -= radian * deltaTime / 1000;\n this._needsUpdate = true;\n } else if (this._rotateVelocity.len() > 0) {\n this._needsUpdate = true;\n }\n\n if (Math.abs(this._zoomSpeed) > 0.1 || this._panVelocity.len() > 0) {\n this._needsUpdate = true;\n }\n\n if (!this._needsUpdate) {\n return;\n }\n\n deltaTime = Math.min(deltaTime, 50);\n\n this._updateDistanceOrSize(deltaTime);\n\n this._updatePan(deltaTime);\n\n this._updateRotate(deltaTime);\n\n this._updateTransform();\n\n this.getCamera().update();\n this.zr && this.zr.refresh();\n this.trigger('update');\n this._needsUpdate = false;\n },\n _updateRotate: function (deltaTime) {\n var velocity = this._rotateVelocity;\n this._phi = velocity.y * deltaTime / 20 + this._phi;\n this._theta = velocity.x * deltaTime / 20 + this._theta;\n this.setAlpha(this.getAlpha());\n this.setBeta(this.getBeta());\n\n this._vectorDamping(velocity, Math.pow(this.damping, deltaTime / 16));\n },\n _updateDistanceOrSize: function (deltaTime) {\n if (this._projection === 'perspective') {\n this._setDistance(this._distance + this._zoomSpeed * deltaTime / 20);\n } else {\n this._setOrthoSize(this._orthoSize + this._zoomSpeed * deltaTime / 20);\n }\n\n this._zoomSpeed *= Math.pow(this.damping, deltaTime / 16);\n },\n _setDistance: function (distance) {\n this._distance = Math.max(Math.min(distance, this.maxDistance), this.minDistance);\n },\n _setOrthoSize: function (size) {\n this._orthoSize = Math.max(Math.min(size, this.maxOrthographicSize), this.minOrthographicSize);\n var camera = this.getCamera();\n var cameraHeight = this._orthoSize;\n var cameraWidth = cameraHeight / this.viewGL.viewport.height * this.viewGL.viewport.width;\n camera.left = -cameraWidth / 2;\n camera.right = cameraWidth / 2;\n camera.top = cameraHeight / 2;\n camera.bottom = -cameraHeight / 2;\n },\n _updatePan: function (deltaTime) {\n var velocity = this._panVelocity;\n var len = this._distance;\n var target = this.getCamera();\n var yAxis = target.worldTransform.y;\n var xAxis = target.worldTransform.x; // PENDING\n\n this._center.scaleAndAdd(xAxis, -velocity.x * len / 200).scaleAndAdd(yAxis, -velocity.y * len / 200);\n\n this._vectorDamping(velocity, 0);\n },\n _updateTransform: function () {\n var camera = this.getCamera();\n var dir = new Vector3();\n var theta = this._theta + Math.PI / 2;\n var phi = this._phi + Math.PI / 2;\n var r = Math.sin(theta);\n dir.x = r * Math.cos(phi);\n dir.y = -Math.cos(theta);\n dir.z = r * Math.sin(phi);\n camera.position.copy(this._center).scaleAndAdd(dir, this._distance);\n camera.rotation.identity() // First around y, then around x\n .rotateY(-this._phi).rotateX(-this._theta);\n },\n _startCountingStill: function () {\n clearTimeout(this._stillTimeout);\n var time = this.autoRotateAfterStill;\n var self = this;\n\n if (!isNaN(time) && time > 0) {\n this._stillTimeout = setTimeout(function () {\n self._rotating = true;\n }, time * 1000);\n }\n },\n _vectorDamping: function (v, damping) {\n var speed = v.len();\n speed = speed * damping;\n\n if (speed < 1e-4) {\n speed = 0;\n }\n\n v.normalize().scale(speed);\n },\n _decomposeTransform: function () {\n if (!this.getCamera()) {\n return;\n }\n\n this.getCamera().updateWorldTransform();\n var forward = this.getCamera().worldTransform.z;\n var alpha = Math.asin(forward.y);\n var beta = Math.atan2(forward.x, forward.z);\n this._theta = alpha;\n this._phi = -beta;\n this.setBeta(this.getBeta());\n this.setAlpha(this.getAlpha()); // Is perspective\n\n if (this.getCamera().aspect) {\n this._setDistance(this.getCamera().position.dist(this._center));\n } else {\n this._setOrthoSize(this.getCamera().top - this.getCamera().bottom);\n }\n },\n _mouseDownHandler: function (e) {\n if (e.target) {\n // If mouseon some zrender element.\n return;\n }\n\n if (this._isAnimating()) {\n return;\n }\n\n var x = e.offsetX;\n var y = e.offsetY;\n\n if (this.viewGL && !this.viewGL.containPoint(x, y)) {\n return;\n }\n\n this.zr.on('mousemove', this._mouseMoveHandler);\n this.zr.on('mouseup', this._mouseUpHandler);\n\n if (e.event.targetTouches) {\n if (e.event.targetTouches.length === 1) {\n this._mode = 'rotate';\n }\n } else {\n if (e.event.button === MOUSE_BUTTON_KEY_MAP[this.rotateMouseButton]) {\n this._mode = 'rotate';\n } else if (e.event.button === MOUSE_BUTTON_KEY_MAP[this.panMouseButton]) {\n this._mode = 'pan';\n } else {\n this._mode = '';\n }\n } // Reset rotate velocity\n\n\n this._rotateVelocity.set(0, 0);\n\n this._rotating = false;\n\n if (this.autoRotate) {\n this._startCountingStill();\n }\n\n this._mouseX = e.offsetX;\n this._mouseY = e.offsetY;\n },\n _mouseMoveHandler: function (e) {\n if (e.target && e.target.__isGLToZRProxy) {\n return;\n }\n\n if (this._isAnimating()) {\n return;\n }\n\n var panSensitivity = convertToArray(this.panSensitivity);\n var rotateSensitivity = convertToArray(this.rotateSensitivity);\n\n if (this._mode === 'rotate') {\n this._rotateVelocity.y = (e.offsetX - this._mouseX) / this.zr.getHeight() * 2 * rotateSensitivity[0];\n this._rotateVelocity.x = (e.offsetY - this._mouseY) / this.zr.getWidth() * 2 * rotateSensitivity[1];\n } else if (this._mode === 'pan') {\n this._panVelocity.x = (e.offsetX - this._mouseX) / this.zr.getWidth() * panSensitivity[0] * 400;\n this._panVelocity.y = (-e.offsetY + this._mouseY) / this.zr.getHeight() * panSensitivity[1] * 400;\n }\n\n this._mouseX = e.offsetX;\n this._mouseY = e.offsetY;\n e.event.preventDefault();\n },\n _mouseWheelHandler: function (e) {\n if (this._isAnimating()) {\n return;\n }\n\n var delta = e.event.wheelDelta // Webkit\n || -e.event.detail; // Firefox\n\n this._zoomHandler(e, delta);\n },\n _pinchHandler: function (e) {\n if (this._isAnimating()) {\n return;\n }\n\n this._zoomHandler(e, e.pinchScale > 1 ? 1 : -1); // Not rotate when pinch\n\n\n this._mode = '';\n },\n _zoomHandler: function (e, delta) {\n if (delta === 0) {\n return;\n }\n\n var x = e.offsetX;\n var y = e.offsetY;\n\n if (this.viewGL && !this.viewGL.containPoint(x, y)) {\n return;\n }\n\n var speed;\n\n if (this._projection === 'perspective') {\n speed = Math.max(Math.max(Math.min(this._distance - this.minDistance, this.maxDistance - this._distance)) / 20, 0.5);\n } else {\n speed = Math.max(Math.max(Math.min(this._orthoSize - this.minOrthographicSize, this.maxOrthographicSize - this._orthoSize)) / 20, 0.5);\n }\n\n this._zoomSpeed = (delta > 0 ? -1 : 1) * speed * this.zoomSensitivity;\n this._rotating = false;\n\n if (this.autoRotate && this._mode === 'rotate') {\n this._startCountingStill();\n }\n\n e.event.preventDefault();\n },\n _mouseUpHandler: function () {\n this.zr.off('mousemove', this._mouseMoveHandler);\n this.zr.off('mouseup', this._mouseUpHandler);\n },\n _isRightMouseButtonUsed: function () {\n return this.rotateMouseButton === 'right' || this.panMouseButton === 'right';\n },\n _contextMenuHandler: function (e) {\n if (this._isRightMouseButtonUsed()) {\n e.preventDefault();\n }\n },\n _addAnimator: function (animator) {\n var animators = this._animators;\n animators.push(animator);\n animator.done(function () {\n var idx = animators.indexOf(animator);\n\n if (idx >= 0) {\n animators.splice(idx, 1);\n }\n });\n return animator;\n }\n});\n/**\n * If auto rotate the target\n * @type {boolean}\n * @default false\n */\n\nObject.defineProperty(OrbitControl.prototype, 'autoRotate', {\n get: function (val) {\n return this._autoRotate;\n },\n set: function (val) {\n this._autoRotate = val;\n this._rotating = val;\n }\n});\nexport default OrbitControl;","export default {\n convertToDynamicArray: function (clear) {\n if (clear) {\n this.resetOffset();\n }\n\n var attributes = this.attributes;\n\n for (var name in attributes) {\n if (clear || !attributes[name].value) {\n attributes[name].value = [];\n } else {\n attributes[name].value = Array.prototype.slice.call(attributes[name].value);\n }\n }\n\n if (clear || !this.indices) {\n this.indices = [];\n } else {\n this.indices = Array.prototype.slice.call(this.indices);\n }\n },\n convertToTypedArray: function () {\n var attributes = this.attributes;\n\n for (var name in attributes) {\n if (attributes[name].value && attributes[name].value.length > 0) {\n attributes[name].value = new Float32Array(attributes[name].value);\n } else {\n attributes[name].value = null;\n }\n }\n\n if (this.indices && this.indices.length > 0) {\n this.indices = this.vertexCount > 0xffff ? new Uint32Array(this.indices) : new Uint16Array(this.indices);\n }\n\n this.dirty();\n }\n};","/**\n * @fileoverview gl-matrix - High performance matrix and vector operations\n * @author Brandon Jones\n * @author Colin MacKenzie IV\n * @version 2.2.2\n */\n\n/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\n * Redistributions of source code must retain the above copyright notice, this\n list of conditions and the following disclaimer.\n * Redistributions in binary form must reproduce the above copyright notice,\n this list of conditions and the following disclaimer in the documentation\n and/or other materials provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR\nANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\nANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */\n\nimport vec2 from './vec2';\nimport vec3 from './vec3';\nimport vec4 from './vec4';\nimport mat2 from './mat2';\nimport mat2d from './mat2d';\nimport mat3 from './mat3';\nimport mat4 from './mat4';\nimport quat from './quat';\n\nexport default {\n vec2: vec2,\n vec3: vec3,\n vec4: vec4,\n mat2: mat2,\n mat2d: mat2d,\n mat3: mat3,\n mat4: mat4,\n quat: quat\n};\n","// DEPRECATED\nimport glmatrix from '../glmatrix';\n\nexport default glmatrix;\n","/**\n * Lines geometry\n * Use screen space projected lines lineWidth > MAX_LINE_WIDTH\n * https://mattdesl.svbtle.com/drawing-lines-is-hard\n * @module echarts-gl/util/geometry/LinesGeometry\n * @author Yi Shen(http://github.com/pissang)\n */\nimport Geometry from 'claygl/src/Geometry';\nimport * as echarts from 'echarts/lib/echarts';\nimport dynamicConvertMixin from './dynamicConvertMixin';\nimport glmatrix from 'claygl/src/dep/glmatrix';\nvar vec3 = glmatrix.vec3; // var CURVE_RECURSION_LIMIT = 8;\n// var CURVE_COLLINEAR_EPSILON = 40;\n\nvar sampleLinePoints = [[0, 0], [1, 1]];\n/**\n * @constructor\n * @alias module:echarts-gl/util/geometry/LinesGeometry\n * @extends clay.Geometry\n */\n\nvar LinesGeometry = Geometry.extend(function () {\n return {\n segmentScale: 1,\n dynamic: true,\n\n /**\n * Need to use mesh to expand lines if lineWidth > MAX_LINE_WIDTH\n */\n useNativeLine: true,\n attributes: {\n position: new Geometry.Attribute('position', 'float', 3, 'POSITION'),\n positionPrev: new Geometry.Attribute('positionPrev', 'float', 3),\n positionNext: new Geometry.Attribute('positionNext', 'float', 3),\n prevPositionPrev: new Geometry.Attribute('prevPositionPrev', 'float', 3),\n prevPosition: new Geometry.Attribute('prevPosition', 'float', 3),\n prevPositionNext: new Geometry.Attribute('prevPositionNext', 'float', 3),\n offset: new Geometry.Attribute('offset', 'float', 1),\n color: new Geometry.Attribute('color', 'float', 4, 'COLOR')\n }\n };\n},\n/** @lends module: echarts-gl/util/geometry/LinesGeometry.prototype */\n{\n /**\n * Reset offset\n */\n resetOffset: function () {\n this._vertexOffset = 0;\n this._triangleOffset = 0;\n this._itemVertexOffsets = [];\n },\n\n /**\n * @param {number} nVertex\n */\n setVertexCount: function (nVertex) {\n var attributes = this.attributes;\n\n if (this.vertexCount !== nVertex) {\n attributes.position.init(nVertex);\n attributes.color.init(nVertex);\n\n if (!this.useNativeLine) {\n attributes.positionPrev.init(nVertex);\n attributes.positionNext.init(nVertex);\n attributes.offset.init(nVertex);\n }\n\n if (nVertex > 0xffff) {\n if (this.indices instanceof Uint16Array) {\n this.indices = new Uint32Array(this.indices);\n }\n } else {\n if (this.indices instanceof Uint32Array) {\n this.indices = new Uint16Array(this.indices);\n }\n }\n }\n },\n\n /**\n * @param {number} nTriangle\n */\n setTriangleCount: function (nTriangle) {\n if (this.triangleCount !== nTriangle) {\n if (nTriangle === 0) {\n this.indices = null;\n } else {\n this.indices = this.vertexCount > 0xffff ? new Uint32Array(nTriangle * 3) : new Uint16Array(nTriangle * 3);\n }\n }\n },\n _getCubicCurveApproxStep: function (p0, p1, p2, p3) {\n var len = vec3.dist(p0, p1) + vec3.dist(p2, p1) + vec3.dist(p3, p2);\n var step = 1 / (len + 1) * this.segmentScale;\n return step;\n },\n\n /**\n * Get vertex count of cubic curve\n * @param {Array.} p0\n * @param {Array.} p1\n * @param {Array.} p2\n * @param {Array.} p3\n * @return number\n */\n getCubicCurveVertexCount: function (p0, p1, p2, p3) {\n var step = this._getCubicCurveApproxStep(p0, p1, p2, p3);\n\n var segCount = Math.ceil(1 / step);\n\n if (!this.useNativeLine) {\n return segCount * 2 + 2;\n } else {\n return segCount * 2;\n }\n },\n\n /**\n * Get face count of cubic curve\n * @param {Array.} p0\n * @param {Array.} p1\n * @param {Array.} p2\n * @param {Array.} p3\n * @return number\n */\n getCubicCurveTriangleCount: function (p0, p1, p2, p3) {\n var step = this._getCubicCurveApproxStep(p0, p1, p2, p3);\n\n var segCount = Math.ceil(1 / step);\n\n if (!this.useNativeLine) {\n return segCount * 2;\n } else {\n return 0;\n }\n },\n\n /**\n * Get vertex count of line\n * @return {number}\n */\n getLineVertexCount: function () {\n return this.getPolylineVertexCount(sampleLinePoints);\n },\n\n /**\n * Get face count of line\n * @return {number}\n */\n getLineTriangleCount: function () {\n return this.getPolylineTriangleCount(sampleLinePoints);\n },\n\n /**\n * Get how many vertices will polyline take.\n * @type {number|Array} points Can be a 1d/2d list of points, or a number of points amount.\n * @return {number}\n */\n getPolylineVertexCount: function (points) {\n var pointsLen;\n\n if (typeof points === 'number') {\n pointsLen = points;\n } else {\n var is2DArray = typeof points[0] !== 'number';\n pointsLen = is2DArray ? points.length : points.length / 3;\n }\n\n return !this.useNativeLine ? (pointsLen - 1) * 2 + 2 : (pointsLen - 1) * 2;\n },\n\n /**\n * Get how many triangles will polyline take.\n * @type {number|Array} points Can be a 1d/2d list of points, or a number of points amount.\n * @return {number}\n */\n getPolylineTriangleCount: function (points) {\n var pointsLen;\n\n if (typeof points === 'number') {\n pointsLen = points;\n } else {\n var is2DArray = typeof points[0] !== 'number';\n pointsLen = is2DArray ? points.length : points.length / 3;\n }\n\n return !this.useNativeLine ? Math.max(pointsLen - 1, 0) * 2 : 0;\n },\n\n /**\n * Add a cubic curve\n * @param {Array.} p0\n * @param {Array.} p1\n * @param {Array.} p2\n * @param {Array.} p3\n * @param {Array.} color\n * @param {number} [lineWidth=1]\n */\n addCubicCurve: function (p0, p1, p2, p3, color, lineWidth) {\n if (lineWidth == null) {\n lineWidth = 1;\n } // incremental interpolation\n // http://antigrain.com/research/bezier_interpolation/index.html#PAGE_BEZIER_INTERPOLATION\n\n\n var x0 = p0[0],\n y0 = p0[1],\n z0 = p0[2];\n var x1 = p1[0],\n y1 = p1[1],\n z1 = p1[2];\n var x2 = p2[0],\n y2 = p2[1],\n z2 = p2[2];\n var x3 = p3[0],\n y3 = p3[1],\n z3 = p3[2];\n\n var step = this._getCubicCurveApproxStep(p0, p1, p2, p3);\n\n var step2 = step * step;\n var step3 = step2 * step;\n var pre1 = 3.0 * step;\n var pre2 = 3.0 * step2;\n var pre4 = 6.0 * step2;\n var pre5 = 6.0 * step3;\n var tmp1x = x0 - x1 * 2.0 + x2;\n var tmp1y = y0 - y1 * 2.0 + y2;\n var tmp1z = z0 - z1 * 2.0 + z2;\n var tmp2x = (x1 - x2) * 3.0 - x0 + x3;\n var tmp2y = (y1 - y2) * 3.0 - y0 + y3;\n var tmp2z = (z1 - z2) * 3.0 - z0 + z3;\n var fx = x0;\n var fy = y0;\n var fz = z0;\n var dfx = (x1 - x0) * pre1 + tmp1x * pre2 + tmp2x * step3;\n var dfy = (y1 - y0) * pre1 + tmp1y * pre2 + tmp2y * step3;\n var dfz = (z1 - z0) * pre1 + tmp1z * pre2 + tmp2z * step3;\n var ddfx = tmp1x * pre4 + tmp2x * pre5;\n var ddfy = tmp1y * pre4 + tmp2y * pre5;\n var ddfz = tmp1z * pre4 + tmp2z * pre5;\n var dddfx = tmp2x * pre5;\n var dddfy = tmp2y * pre5;\n var dddfz = tmp2z * pre5;\n var t = 0;\n var k = 0;\n var segCount = Math.ceil(1 / step);\n var points = new Float32Array((segCount + 1) * 3);\n var points = [];\n var offset = 0;\n\n for (var k = 0; k < segCount + 1; k++) {\n points[offset++] = fx;\n points[offset++] = fy;\n points[offset++] = fz;\n fx += dfx;\n fy += dfy;\n fz += dfz;\n dfx += ddfx;\n dfy += ddfy;\n dfz += ddfz;\n ddfx += dddfx;\n ddfy += dddfy;\n ddfz += dddfz;\n t += step;\n\n if (t > 1) {\n fx = dfx > 0 ? Math.min(fx, x3) : Math.max(fx, x3);\n fy = dfy > 0 ? Math.min(fy, y3) : Math.max(fy, y3);\n fz = dfz > 0 ? Math.min(fz, z3) : Math.max(fz, z3);\n }\n }\n\n return this.addPolyline(points, color, lineWidth);\n },\n\n /**\n * Add a straight line\n * @param {Array.} p0\n * @param {Array.} p1\n * @param {Array.} color\n * @param {number} [lineWidth=1]\n */\n addLine: function (p0, p1, color, lineWidth) {\n return this.addPolyline([p0, p1], color, lineWidth);\n },\n\n /**\n * Add a straight line\n * @param {Array. | Array.} points\n * @param {Array. | Array.} color\n * @param {number} [lineWidth=1]\n * @param {number} [startOffset=0]\n * @param {number} [pointsCount] Default to be amount of points in the first argument\n */\n addPolyline: function (points, color, lineWidth, startOffset, pointsCount) {\n if (!points.length) {\n return;\n }\n\n var is2DArray = typeof points[0] !== 'number';\n\n if (pointsCount == null) {\n pointsCount = is2DArray ? points.length : points.length / 3;\n }\n\n if (pointsCount < 2) {\n return;\n }\n\n if (startOffset == null) {\n startOffset = 0;\n }\n\n if (lineWidth == null) {\n lineWidth = 1;\n }\n\n this._itemVertexOffsets.push(this._vertexOffset);\n\n var is2DArray = typeof points[0] !== 'number';\n var notSharingColor = is2DArray ? typeof color[0] !== 'number' : color.length / 4 === pointsCount;\n var positionAttr = this.attributes.position;\n var positionPrevAttr = this.attributes.positionPrev;\n var positionNextAttr = this.attributes.positionNext;\n var colorAttr = this.attributes.color;\n var offsetAttr = this.attributes.offset;\n var indices = this.indices;\n var vertexOffset = this._vertexOffset;\n var point;\n var pointColor;\n lineWidth = Math.max(lineWidth, 0.01);\n\n for (var k = startOffset; k < pointsCount; k++) {\n if (is2DArray) {\n point = points[k];\n\n if (notSharingColor) {\n pointColor = color[k];\n } else {\n pointColor = color;\n }\n } else {\n var k3 = k * 3;\n point = point || [];\n point[0] = points[k3];\n point[1] = points[k3 + 1];\n point[2] = points[k3 + 2];\n\n if (notSharingColor) {\n var k4 = k * 4;\n pointColor = pointColor || [];\n pointColor[0] = color[k4];\n pointColor[1] = color[k4 + 1];\n pointColor[2] = color[k4 + 2];\n pointColor[3] = color[k4 + 3];\n } else {\n pointColor = color;\n }\n }\n\n if (!this.useNativeLine) {\n if (k < pointsCount - 1) {\n // Set to next two points\n positionPrevAttr.set(vertexOffset + 2, point);\n positionPrevAttr.set(vertexOffset + 3, point);\n }\n\n if (k > 0) {\n // Set to previous two points\n positionNextAttr.set(vertexOffset - 2, point);\n positionNextAttr.set(vertexOffset - 1, point);\n }\n\n positionAttr.set(vertexOffset, point);\n positionAttr.set(vertexOffset + 1, point);\n colorAttr.set(vertexOffset, pointColor);\n colorAttr.set(vertexOffset + 1, pointColor);\n offsetAttr.set(vertexOffset, lineWidth / 2);\n offsetAttr.set(vertexOffset + 1, -lineWidth / 2);\n vertexOffset += 2;\n } else {\n if (k > 1) {\n positionAttr.copy(vertexOffset, vertexOffset - 1);\n colorAttr.copy(vertexOffset, vertexOffset - 1);\n vertexOffset++;\n }\n }\n\n if (!this.useNativeLine) {\n if (k > 0) {\n var idx3 = this._triangleOffset * 3;\n var indices = this.indices; // 0-----2\n // 1-----3\n // 0->1->2, 1->3->2\n\n indices[idx3] = vertexOffset - 4;\n indices[idx3 + 1] = vertexOffset - 3;\n indices[idx3 + 2] = vertexOffset - 2;\n indices[idx3 + 3] = vertexOffset - 3;\n indices[idx3 + 4] = vertexOffset - 1;\n indices[idx3 + 5] = vertexOffset - 2;\n this._triangleOffset += 2;\n }\n } else {\n colorAttr.set(vertexOffset, pointColor);\n positionAttr.set(vertexOffset, point);\n vertexOffset++;\n }\n }\n\n if (!this.useNativeLine) {\n var start = this._vertexOffset;\n var end = this._vertexOffset + pointsCount * 2;\n positionPrevAttr.copy(start, start + 2);\n positionPrevAttr.copy(start + 1, start + 3);\n positionNextAttr.copy(end - 1, end - 3);\n positionNextAttr.copy(end - 2, end - 4);\n }\n\n this._vertexOffset = vertexOffset;\n return this._vertexOffset;\n },\n\n /**\n * Set color of single line.\n */\n setItemColor: function (idx, color) {\n var startOffset = this._itemVertexOffsets[idx];\n var endOffset = idx < this._itemVertexOffsets.length - 1 ? this._itemVertexOffsets[idx + 1] : this._vertexOffset;\n\n for (var i = startOffset; i < endOffset; i++) {\n this.attributes.color.set(i, color);\n }\n\n this.dirty('color');\n },\n\n /**\n * @return {number}\n */\n currentTriangleOffset: function () {\n return this._triangleOffset;\n },\n\n /**\n * @return {number}\n */\n currentVertexOffset: function () {\n return this._vertexOffset;\n }\n});\necharts.util.defaults(LinesGeometry.prototype, dynamicConvertMixin);\nexport default LinesGeometry;","/**\n * Texture Atlas for the sprites.\n * It uses zrender for 2d element management and rendering\n * @module echarts-gl/util/ZRTextureAtlasSurface\n */\n// TODO Expand.\nimport * as echarts from 'echarts/lib/echarts';\nimport Texture2D from 'claygl/src/Texture2D';\n\nfunction ZRTextureAtlasSurfaceNode(zr, offsetX, offsetY, width, height, gap, dpr) {\n this._zr = zr;\n /**\n * Current cursor x\n * @type {number}\n * @private\n */\n\n this._x = 0;\n /**\n * Current cursor y\n * @type {number}\n */\n\n this._y = 0;\n this._rowHeight = 0;\n /**\n * width without dpr.\n * @type {number}\n * @private\n */\n\n this.width = width;\n /**\n * height without dpr.\n * @type {number}\n * @private\n */\n\n this.height = height;\n /**\n * offsetX without dpr\n * @type {number}\n */\n\n this.offsetX = offsetX;\n /**\n * offsetY without dpr\n * @type {number}\n */\n\n this.offsetY = offsetY;\n this.dpr = dpr;\n this.gap = gap;\n}\n\nZRTextureAtlasSurfaceNode.prototype = {\n constructor: ZRTextureAtlasSurfaceNode,\n clear: function () {\n this._x = 0;\n this._y = 0;\n this._rowHeight = 0;\n },\n\n /**\n * Add shape to atlas\n * @param {module:zrender/graphic/Displayable} shape\n * @param {number} width\n * @param {number} height\n * @return {Array}\n */\n add: function (el, width, height) {\n // FIXME Text element not consider textAlign and textVerticalAlign.\n // TODO, inner text, shadow\n var rect = el.getBoundingRect(); // FIXME aspect ratio\n\n if (width == null) {\n width = rect.width;\n }\n\n if (height == null) {\n height = rect.height;\n }\n\n width *= this.dpr;\n height *= this.dpr;\n\n this._fitElement(el, width, height); // var aspect = el.scale[1] / el.scale[0];\n // Adjust aspect ratio to make the text more clearly\n // FIXME If height > width, width is useless ?\n // width = height * aspect;\n // el.position[0] *= aspect;\n // el.scale[0] = el.scale[1];\n\n\n var x = this._x;\n var y = this._y;\n var canvasWidth = this.width * this.dpr;\n var canvasHeight = this.height * this.dpr;\n var gap = this.gap;\n\n if (x + width + gap > canvasWidth) {\n // Change a new row\n x = this._x = 0;\n y += this._rowHeight + gap;\n this._y = y; // Reset row height\n\n this._rowHeight = 0;\n }\n\n this._x += width + gap;\n this._rowHeight = Math.max(this._rowHeight, height);\n\n if (y + height + gap > canvasHeight) {\n // There is no space anymore\n return null;\n } // Shift the el\n\n\n el.x += this.offsetX * this.dpr + x;\n el.y += this.offsetY * this.dpr + y;\n\n this._zr.add(el);\n\n var coordsOffset = [this.offsetX / this.width, this.offsetY / this.height];\n var coords = [[x / canvasWidth + coordsOffset[0], y / canvasHeight + coordsOffset[1]], [(x + width) / canvasWidth + coordsOffset[0], (y + height) / canvasHeight + coordsOffset[1]]];\n return coords;\n },\n\n /**\n * Fit element size by correct its position and scaling\n * @param {module:zrender/graphic/Displayable} el\n * @param {number} spriteWidth\n * @param {number} spriteHeight\n */\n _fitElement: function (el, spriteWidth, spriteHeight) {\n // TODO, inner text, shadow\n var rect = el.getBoundingRect();\n var scaleX = spriteWidth / rect.width;\n var scaleY = spriteHeight / rect.height;\n el.x = -rect.x * scaleX;\n el.y = -rect.y * scaleY;\n el.scaleX = scaleX;\n el.scaleY = scaleY;\n el.update();\n }\n};\n/**\n * constructor\n * @alias module:echarts-gl/util/ZRTextureAtlasSurface\n * @param {number} opt.width\n * @param {number} opt.height\n * @param {number} opt.devicePixelRatio\n * @param {number} opt.gap Gap for safe.\n * @param {Function} opt.onupdate\n */\n\nfunction ZRTextureAtlasSurface(opt) {\n opt = opt || {};\n opt.width = opt.width || 512;\n opt.height = opt.height || 512;\n opt.devicePixelRatio = opt.devicePixelRatio || 1;\n opt.gap = opt.gap == null ? 2 : opt.gap;\n var canvas = document.createElement('canvas');\n canvas.width = opt.width * opt.devicePixelRatio;\n canvas.height = opt.height * opt.devicePixelRatio;\n this._canvas = canvas;\n this._texture = new Texture2D({\n image: canvas,\n flipY: false\n });\n var self = this;\n /**\n * zrender instance in the Chart\n * @type {zrender~ZRender}\n */\n\n this._zr = echarts.zrender.init(canvas);\n var oldRefreshImmediately = this._zr.refreshImmediately;\n\n this._zr.refreshImmediately = function () {\n oldRefreshImmediately.call(this);\n\n self._texture.dirty();\n\n self.onupdate && self.onupdate();\n };\n\n this._dpr = opt.devicePixelRatio;\n /**\n * Texture coords map for each sprite image\n * @type {Object}\n */\n\n this._coords = {};\n this.onupdate = opt.onupdate;\n this._gap = opt.gap; // Left sub atlas.\n\n this._textureAtlasNodes = [new ZRTextureAtlasSurfaceNode(this._zr, 0, 0, opt.width, opt.height, this._gap, this._dpr)];\n this._nodeWidth = opt.width;\n this._nodeHeight = opt.height;\n this._currentNodeIdx = 0;\n}\n\nZRTextureAtlasSurface.prototype = {\n /**\n * Clear the texture atlas\n */\n clear: function () {\n for (var i = 0; i < this._textureAtlasNodes.length; i++) {\n this._textureAtlasNodes[i].clear();\n }\n\n this._currentNodeIdx = 0;\n\n this._zr.clear();\n\n this._coords = {};\n },\n\n /**\n * @return {number}\n */\n getWidth: function () {\n return this._width;\n },\n\n /**\n * @return {number}\n */\n getHeight: function () {\n return this._height;\n },\n\n /**\n * @return {number}\n */\n getTexture: function () {\n return this._texture;\n },\n\n /**\n * @return {number}\n */\n getDevicePixelRatio: function () {\n return this._dpr;\n },\n getZr: function () {\n return this._zr;\n },\n _getCurrentNode: function () {\n return this._textureAtlasNodes[this._currentNodeIdx];\n },\n _expand: function () {\n this._currentNodeIdx++;\n\n if (this._textureAtlasNodes[this._currentNodeIdx]) {\n // Use the node created previously.\n return this._textureAtlasNodes[this._currentNodeIdx];\n }\n\n var maxSize = 4096 / this._dpr;\n var textureAtlasNodes = this._textureAtlasNodes;\n var nodeLen = textureAtlasNodes.length;\n var offsetX = nodeLen * this._nodeWidth % maxSize;\n\n var offsetY = Math.floor(nodeLen * this._nodeWidth / maxSize) * this._nodeHeight;\n\n if (offsetY >= maxSize) {\n // Failed if image is too large.\n if (process.env.NODE_ENV !== 'production') {\n console.error('Too much labels. Some will be ignored.');\n }\n\n return;\n }\n\n var width = (offsetX + this._nodeWidth) * this._dpr;\n var height = (offsetY + this._nodeHeight) * this._dpr;\n\n try {\n // Resize will error in node.\n this._zr.resize({\n width: width,\n height: height\n });\n } catch (e) {\n this._canvas.width = width;\n this._canvas.height = height;\n }\n\n var newNode = new ZRTextureAtlasSurfaceNode(this._zr, offsetX, offsetY, this._nodeWidth, this._nodeHeight, this._gap, this._dpr);\n\n this._textureAtlasNodes.push(newNode);\n\n return newNode;\n },\n add: function (el, width, height) {\n if (this._coords[el.id]) {\n if (process.env.NODE_ENV !== 'production') {\n console.warn('Element already been add');\n }\n\n return this._coords[el.id];\n }\n\n var coords = this._getCurrentNode().add(el, width, height);\n\n if (!coords) {\n var newNode = this._expand();\n\n if (!newNode) {\n // To maximum\n return;\n }\n\n coords = newNode.add(el, width, height);\n }\n\n this._coords[el.id] = coords;\n return coords;\n },\n\n /**\n * Get coord scale after texture atlas is expanded.\n * @return {Array.}\n */\n getCoordsScale: function () {\n var dpr = this._dpr;\n return [this._nodeWidth / this._canvas.width * dpr, this._nodeHeight / this._canvas.height * dpr];\n },\n\n /**\n * Get texture coords of sprite image\n * @param {string} id Image id\n * @return {Array}\n */\n getCoords: function (id) {\n return this._coords[id];\n },\n dispose: function () {\n this._zr.dispose();\n }\n};\nexport default ZRTextureAtlasSurface;","import graphicGL from '../../util/graphicGL';\nimport Skybox from 'claygl/src/plugin/Skybox';\nimport * as echarts from 'echarts/lib/echarts';\n\nfunction SceneHelper() {}\n\nSceneHelper.prototype = {\n constructor: SceneHelper,\n setScene: function (scene) {\n this._scene = scene;\n\n if (this._skybox) {\n this._skybox.attachScene(this._scene);\n }\n },\n initLight: function (rootNode) {\n this._lightRoot = rootNode;\n /**\n * @type {clay.light.Directional}\n */\n\n this.mainLight = new graphicGL.DirectionalLight({\n shadowBias: 0.005\n });\n /**\n * @type {clay.light.Ambient}\n */\n\n this.ambientLight = new graphicGL.AmbientLight();\n rootNode.add(this.mainLight);\n rootNode.add(this.ambientLight);\n },\n dispose: function () {\n if (this._lightRoot) {\n this._lightRoot.remove(this.mainLight);\n\n this._lightRoot.remove(this.ambientLight);\n }\n },\n updateLight: function (componentModel) {\n var mainLight = this.mainLight;\n var ambientLight = this.ambientLight;\n var lightModel = componentModel.getModel('light');\n var mainLightModel = lightModel.getModel('main');\n var ambientLightModel = lightModel.getModel('ambient');\n mainLight.intensity = mainLightModel.get('intensity');\n ambientLight.intensity = ambientLightModel.get('intensity');\n mainLight.color = graphicGL.parseColor(mainLightModel.get('color')).slice(0, 3);\n ambientLight.color = graphicGL.parseColor(ambientLightModel.get('color')).slice(0, 3);\n var alpha = mainLightModel.get('alpha') || 0;\n var beta = mainLightModel.get('beta') || 0;\n mainLight.position.setArray(graphicGL.directionFromAlphaBeta(alpha, beta));\n mainLight.lookAt(graphicGL.Vector3.ZERO);\n mainLight.castShadow = mainLightModel.get('shadow');\n mainLight.shadowResolution = graphicGL.getShadowResolution(mainLightModel.get('shadowQuality'));\n },\n updateAmbientCubemap: function (renderer, componentModel, api) {\n var ambientCubemapModel = componentModel.getModel('light.ambientCubemap');\n var textureUrl = ambientCubemapModel.get('texture');\n\n if (textureUrl) {\n this._cubemapLightsCache = this._cubemapLightsCache || {};\n var lights = this._cubemapLightsCache[textureUrl];\n\n if (!lights) {\n var self = this;\n lights = this._cubemapLightsCache[textureUrl] = graphicGL.createAmbientCubemap(ambientCubemapModel.option, renderer, api, function () {\n // Use prefitered cubemap\n if (self._isSkyboxFromAmbientCubemap) {\n self._skybox.setEnvironmentMap(lights.specular.cubemap);\n }\n\n api.getZr().refresh();\n });\n }\n\n this._lightRoot.add(lights.diffuse);\n\n this._lightRoot.add(lights.specular);\n\n this._currentCubemapLights = lights;\n } else if (this._currentCubemapLights) {\n this._lightRoot.remove(this._currentCubemapLights.diffuse);\n\n this._lightRoot.remove(this._currentCubemapLights.specular);\n\n this._currentCubemapLights = null;\n }\n },\n updateSkybox: function (renderer, componentModel, api) {\n var environmentUrl = componentModel.get('environment');\n var self = this;\n\n function getSkybox() {\n self._skybox = self._skybox || new Skybox();\n return self._skybox;\n }\n\n var skybox = getSkybox();\n\n if (environmentUrl && environmentUrl !== 'none') {\n if (environmentUrl === 'auto') {\n this._isSkyboxFromAmbientCubemap = true; // Use environment in ambient cubemap\n\n if (this._currentCubemapLights) {\n var cubemap = this._currentCubemapLights.specular.cubemap;\n skybox.setEnvironmentMap(cubemap);\n\n if (this._scene) {\n skybox.attachScene(this._scene);\n }\n\n skybox.material.set('lod', 3);\n } else if (this._skybox) {\n this._skybox.detachScene();\n }\n } // Is gradient or color string\n else if (typeof environmentUrl === 'object' && environmentUrl.colorStops || typeof environmentUrl === 'string' && echarts.color.parse(environmentUrl)) {\n this._isSkyboxFromAmbientCubemap = false;\n var texture = new graphicGL.Texture2D({\n anisotropic: 8,\n flipY: false\n });\n skybox.setEnvironmentMap(texture);\n var canvas = texture.image = document.createElement('canvas');\n canvas.width = canvas.height = 16;\n var ctx = canvas.getContext('2d');\n var rect = new echarts.graphic.Rect({\n shape: {\n x: 0,\n y: 0,\n width: 16,\n height: 16\n },\n style: {\n fill: environmentUrl\n }\n });\n echarts.innerDrawElementOnCanvas(ctx, rect);\n skybox.attachScene(this._scene);\n } else {\n this._isSkyboxFromAmbientCubemap = false; // Panorama\n\n var texture = graphicGL.loadTexture(environmentUrl, api, {\n anisotropic: 8,\n flipY: false\n });\n skybox.setEnvironmentMap(texture);\n skybox.attachScene(this._scene);\n }\n } else {\n if (this._skybox) {\n this._skybox.detachScene(this._scene);\n }\n\n this._skybox = null;\n }\n\n var coordSys = componentModel.coordinateSystem;\n\n if (this._skybox) {\n if (coordSys && coordSys.viewGL && environmentUrl !== 'auto' && !(environmentUrl.match && environmentUrl.match(/.hdr$/))) {\n var srgbDefineMethod = coordSys.viewGL.isLinearSpace() ? 'define' : 'undefine';\n\n this._skybox.material[srgbDefineMethod]('fragment', 'SRGB_DECODE');\n } else {\n this._skybox.material.undefine('fragment', 'SRGB_DECODE');\n } // var ambientCubemapUrl = environmentUrl === 'auto'\n // ? componentModel.get('light.ambientCubemap.texture')\n // : environmentUrl;\n\n }\n }\n};\nexport default SceneHelper;","/**\n * @module echarts-gl/util/geometry/QuadsGeometry\n * @author Yi Shen(http://github.com/pissang)\n */\nimport Geometry from 'claygl/src/Geometry';\nimport * as echarts from 'echarts/lib/echarts';\nimport dynamicConvertMixin from './dynamicConvertMixin';\nimport glmatrix from 'claygl/src/dep/glmatrix';\nvar vec3 = glmatrix.vec3;\n/**\n * @constructor\n * @alias module:echarts-gl/util/geometry/QuadsGeometry\n * @extends clay.Geometry\n */\n\nvar QuadsGeometry = Geometry.extend(function () {\n return {\n segmentScale: 1,\n\n /**\n * Need to use mesh to expand lines if lineWidth > MAX_LINE_WIDTH\n */\n useNativeLine: true,\n attributes: {\n position: new Geometry.Attribute('position', 'float', 3, 'POSITION'),\n normal: new Geometry.Attribute('normal', 'float', 3, 'NORMAL'),\n color: new Geometry.Attribute('color', 'float', 4, 'COLOR')\n }\n };\n},\n/** @lends module: echarts-gl/util/geometry/QuadsGeometry.prototype */\n{\n /**\n * Reset offset\n */\n resetOffset: function () {\n this._vertexOffset = 0;\n this._faceOffset = 0;\n },\n\n /**\n * @param {number} nQuad\n */\n setQuadCount: function (nQuad) {\n var attributes = this.attributes;\n var vertexCount = this.getQuadVertexCount() * nQuad;\n var triangleCount = this.getQuadTriangleCount() * nQuad;\n\n if (this.vertexCount !== vertexCount) {\n attributes.position.init(vertexCount);\n attributes.normal.init(vertexCount);\n attributes.color.init(vertexCount);\n }\n\n if (this.triangleCount !== triangleCount) {\n this.indices = vertexCount > 0xffff ? new Uint32Array(triangleCount * 3) : new Uint16Array(triangleCount * 3);\n }\n },\n getQuadVertexCount: function () {\n return 4;\n },\n getQuadTriangleCount: function () {\n return 2;\n },\n\n /**\n * Add a quad, which in following order:\n * 0-----1\n * 3-----2\n */\n addQuad: function () {\n var a = vec3.create();\n var b = vec3.create();\n var normal = vec3.create();\n var indices = [0, 3, 1, 3, 2, 1];\n return function (coords, color) {\n var positionAttr = this.attributes.position;\n var normalAttr = this.attributes.normal;\n var colorAttr = this.attributes.color;\n vec3.sub(a, coords[1], coords[0]);\n vec3.sub(b, coords[2], coords[1]);\n vec3.cross(normal, a, b);\n vec3.normalize(normal, normal);\n\n for (var i = 0; i < 4; i++) {\n positionAttr.set(this._vertexOffset + i, coords[i]);\n colorAttr.set(this._vertexOffset + i, color);\n normalAttr.set(this._vertexOffset + i, normal);\n }\n\n var idx = this._faceOffset * 3;\n\n for (var i = 0; i < 6; i++) {\n this.indices[idx + i] = indices[i] + this._vertexOffset;\n }\n\n this._vertexOffset += 4;\n this._faceOffset += 2;\n };\n }()\n});\necharts.util.defaults(QuadsGeometry.prototype, dynamicConvertMixin);\nexport default QuadsGeometry;","import * as echarts from 'echarts/lib/echarts';\nimport graphicGL from '../../util/graphicGL';\nimport retrieve from '../../util/retrieve';\nimport Lines3DGeometry from '../../util/geometry/Lines3D';\nimport QuadsGeometry from '../../util/geometry/Quads';\nvar firstNotNull = retrieve.firstNotNull;\nvar dimIndicesMap = {\n // Left to right\n x: 0,\n // Far to near\n y: 2,\n // Bottom to up\n z: 1\n};\n\nfunction updateFacePlane(node, plane, otherAxis, dir) {\n var coord = [0, 0, 0];\n var distance = dir < 0 ? otherAxis.getExtentMin() : otherAxis.getExtentMax();\n coord[dimIndicesMap[otherAxis.dim]] = distance;\n node.position.setArray(coord);\n node.rotation.identity(); // Negative distance because on the opposite of normal direction.\n\n plane.distance = -Math.abs(distance);\n plane.normal.set(0, 0, 0);\n\n if (otherAxis.dim === 'x') {\n node.rotation.rotateY(dir * Math.PI / 2);\n plane.normal.x = -dir;\n } else if (otherAxis.dim === 'z') {\n node.rotation.rotateX(-dir * Math.PI / 2);\n plane.normal.y = -dir;\n } else {\n if (dir > 0) {\n node.rotation.rotateY(Math.PI);\n }\n\n plane.normal.z = -dir;\n }\n}\n\nfunction Grid3DFace(faceInfo, linesMaterial, quadsMaterial) {\n this.rootNode = new graphicGL.Node();\n var linesMesh = new graphicGL.Mesh({\n geometry: new Lines3DGeometry({\n useNativeLine: false\n }),\n material: linesMaterial,\n castShadow: false,\n ignorePicking: true,\n $ignorePicking: true,\n renderOrder: 1\n });\n var quadsMesh = new graphicGL.Mesh({\n geometry: new QuadsGeometry(),\n material: quadsMaterial,\n castShadow: false,\n culling: false,\n ignorePicking: true,\n $ignorePicking: true,\n renderOrder: 0\n }); // Quads are behind lines.\n\n this.rootNode.add(quadsMesh);\n this.rootNode.add(linesMesh);\n this.faceInfo = faceInfo;\n this.plane = new graphicGL.Plane();\n this.linesMesh = linesMesh;\n this.quadsMesh = quadsMesh;\n}\n\nGrid3DFace.prototype.update = function (grid3DModel, ecModel, api) {\n var cartesian = grid3DModel.coordinateSystem;\n var axes = [cartesian.getAxis(this.faceInfo[0]), cartesian.getAxis(this.faceInfo[1])];\n var lineGeometry = this.linesMesh.geometry;\n var quadsGeometry = this.quadsMesh.geometry;\n lineGeometry.convertToDynamicArray(true);\n quadsGeometry.convertToDynamicArray(true);\n\n this._updateSplitLines(lineGeometry, axes, grid3DModel, api);\n\n this._udpateSplitAreas(quadsGeometry, axes, grid3DModel, api);\n\n lineGeometry.convertToTypedArray();\n quadsGeometry.convertToTypedArray();\n var otherAxis = cartesian.getAxis(this.faceInfo[2]);\n updateFacePlane(this.rootNode, this.plane, otherAxis, this.faceInfo[3]);\n};\n\nGrid3DFace.prototype._updateSplitLines = function (geometry, axes, grid3DModel, api) {\n var dpr = api.getDevicePixelRatio();\n axes.forEach(function (axis, idx) {\n var axisModel = axis.model;\n var otherExtent = axes[1 - idx].getExtent();\n\n if (axis.scale.isBlank()) {\n return;\n }\n\n var splitLineModel = axisModel.getModel('splitLine', grid3DModel.getModel('splitLine')); // Render splitLines\n\n if (splitLineModel.get('show')) {\n var lineStyleModel = splitLineModel.getModel('lineStyle');\n var lineColors = lineStyleModel.get('color');\n var opacity = firstNotNull(lineStyleModel.get('opacity'), 1.0);\n var lineWidth = firstNotNull(lineStyleModel.get('width'), 1.0);\n lineColors = echarts.util.isArray(lineColors) ? lineColors : [lineColors];\n var ticksCoords = axis.getTicksCoords({\n tickModel: splitLineModel\n });\n var count = 0;\n\n for (var i = 0; i < ticksCoords.length; i++) {\n var tickCoord = ticksCoords[i].coord;\n var lineColor = graphicGL.parseColor(lineColors[count % lineColors.length]);\n lineColor[3] *= opacity;\n var p0 = [0, 0, 0];\n var p1 = [0, 0, 0]; // 0 - x, 1 - y\n\n p0[idx] = p1[idx] = tickCoord;\n p0[1 - idx] = otherExtent[0];\n p1[1 - idx] = otherExtent[1];\n geometry.addLine(p0, p1, lineColor, lineWidth * dpr);\n count++;\n }\n }\n });\n};\n\nGrid3DFace.prototype._udpateSplitAreas = function (geometry, axes, grid3DModel, api) {\n axes.forEach(function (axis, idx) {\n var axisModel = axis.model;\n var otherExtent = axes[1 - idx].getExtent();\n\n if (axis.scale.isBlank()) {\n return;\n }\n\n var splitAreaModel = axisModel.getModel('splitArea', grid3DModel.getModel('splitArea')); // Render splitAreas\n\n if (splitAreaModel.get('show')) {\n var areaStyleModel = splitAreaModel.getModel('areaStyle');\n var colors = areaStyleModel.get('color');\n var opacity = firstNotNull(areaStyleModel.get('opacity'), 1.0);\n colors = echarts.util.isArray(colors) ? colors : [colors];\n var ticksCoords = axis.getTicksCoords({\n tickModel: splitAreaModel,\n clamp: true\n });\n var count = 0;\n var prevP0 = [0, 0, 0];\n var prevP1 = [0, 0, 0]; // 0 - x, 1 - y\n\n for (var i = 0; i < ticksCoords.length; i++) {\n var tickCoord = ticksCoords[i].coord;\n var p0 = [0, 0, 0];\n var p1 = [0, 0, 0]; // 0 - x, 1 - y\n\n p0[idx] = p1[idx] = tickCoord;\n p0[1 - idx] = otherExtent[0];\n p1[1 - idx] = otherExtent[1];\n\n if (i === 0) {\n prevP0 = p0;\n prevP1 = p1;\n continue;\n }\n\n var color = graphicGL.parseColor(colors[count % colors.length]);\n color[3] *= opacity;\n geometry.addQuad([prevP0, p0, p1, prevP1], color);\n prevP0 = p0;\n prevP1 = p1;\n count++;\n }\n }\n });\n};\n\nexport default Grid3DFace;","/**\n * Geometry collecting sprites\n *\n * @module echarts-gl/util/geometry/Sprites\n * @author Yi Shen(https://github.com/pissang)\n */\nimport * as echarts from 'echarts/lib/echarts';\nimport Geometry from 'claygl/src/Geometry';\nimport dynamicConvertMixin from './dynamicConvertMixin';\nvar squareTriangles = [0, 1, 2, 0, 2, 3];\nvar SpritesGeometry = Geometry.extend(function () {\n return {\n attributes: {\n position: new Geometry.Attribute('position', 'float', 3, 'POSITION'),\n texcoord: new Geometry.Attribute('texcoord', 'float', 2, 'TEXCOORD_0'),\n offset: new Geometry.Attribute('offset', 'float', 2),\n color: new Geometry.Attribute('color', 'float', 4, 'COLOR')\n }\n };\n}, {\n resetOffset: function () {\n this._vertexOffset = 0;\n this._faceOffset = 0;\n },\n setSpriteCount: function (spriteCount) {\n this._spriteCount = spriteCount;\n var vertexCount = spriteCount * 4;\n var triangleCount = spriteCount * 2;\n\n if (this.vertexCount !== vertexCount) {\n this.attributes.position.init(vertexCount);\n this.attributes.offset.init(vertexCount);\n this.attributes.color.init(vertexCount);\n }\n\n if (this.triangleCount !== triangleCount) {\n this.indices = vertexCount > 0xffff ? new Uint32Array(triangleCount * 3) : new Uint16Array(triangleCount * 3);\n }\n },\n setSpriteAlign: function (spriteOffset, size, align, verticalAlign, margin) {\n if (align == null) {\n align = 'left';\n }\n\n if (verticalAlign == null) {\n verticalAlign = 'top';\n }\n\n var leftOffset, topOffset, rightOffset, bottomOffset;\n margin = margin || 0;\n\n switch (align) {\n case 'left':\n leftOffset = margin;\n rightOffset = size[0] + margin;\n break;\n\n case 'center':\n case 'middle':\n leftOffset = -size[0] / 2;\n rightOffset = size[0] / 2;\n break;\n\n case 'right':\n leftOffset = -size[0] - margin;\n rightOffset = -margin;\n break;\n }\n\n switch (verticalAlign) {\n case 'bottom':\n topOffset = margin;\n bottomOffset = size[1] + margin;\n break;\n\n case 'middle':\n topOffset = -size[1] / 2;\n bottomOffset = size[1] / 2;\n break;\n\n case 'top':\n topOffset = -size[1] - margin;\n bottomOffset = -margin;\n break;\n } // 3----2\n // 0----1\n\n\n var vertexOffset = spriteOffset * 4;\n var offsetAttr = this.attributes.offset;\n offsetAttr.set(vertexOffset, [leftOffset, bottomOffset]);\n offsetAttr.set(vertexOffset + 1, [rightOffset, bottomOffset]);\n offsetAttr.set(vertexOffset + 2, [rightOffset, topOffset]);\n offsetAttr.set(vertexOffset + 3, [leftOffset, topOffset]);\n },\n\n /**\n * Add sprite\n * @param {Array.} position\n * @param {Array.} size [width, height]\n * @param {Array.} coords [leftBottom, rightTop]\n * @param {string} [align='left'] 'left' 'center' 'right'\n * @param {string} [verticalAlign='top'] 'top' 'middle' 'bottom'\n * @param {number} [screenMargin=0]\n */\n addSprite: function (position, size, coords, align, verticalAlign, screenMargin) {\n var vertexOffset = this._vertexOffset;\n this.setSprite(this._vertexOffset / 4, position, size, coords, align, verticalAlign, screenMargin);\n\n for (var i = 0; i < squareTriangles.length; i++) {\n this.indices[this._faceOffset * 3 + i] = squareTriangles[i] + vertexOffset;\n }\n\n this._faceOffset += 2;\n this._vertexOffset += 4;\n return vertexOffset / 4;\n },\n setSprite: function (spriteOffset, position, size, coords, align, verticalAlign, screenMargin) {\n var vertexOffset = spriteOffset * 4;\n var attributes = this.attributes;\n\n for (var i = 0; i < 4; i++) {\n attributes.position.set(vertexOffset + i, position);\n } // 3----2\n // 0----1\n\n\n var texcoordAttr = attributes.texcoord;\n texcoordAttr.set(vertexOffset, [coords[0][0], coords[0][1]]);\n texcoordAttr.set(vertexOffset + 1, [coords[1][0], coords[0][1]]);\n texcoordAttr.set(vertexOffset + 2, [coords[1][0], coords[1][1]]);\n texcoordAttr.set(vertexOffset + 3, [coords[0][0], coords[1][1]]);\n this.setSpriteAlign(spriteOffset, size, align, verticalAlign, screenMargin);\n }\n});\necharts.util.defaults(SpritesGeometry.prototype, dynamicConvertMixin);\nexport default SpritesGeometry;","export default \"@export ecgl.labels.vertex\\n\\nattribute vec3 position: POSITION;\\nattribute vec2 texcoord: TEXCOORD_0;\\nattribute vec2 offset;\\n#ifdef VERTEX_COLOR\\nattribute vec4 a_Color : COLOR;\\nvarying vec4 v_Color;\\n#endif\\n\\nuniform mat4 worldViewProjection : WORLDVIEWPROJECTION;\\nuniform vec4 viewport : VIEWPORT;\\n\\nvarying vec2 v_Texcoord;\\n\\nvoid main()\\n{\\n vec4 proj = worldViewProjection * vec4(position, 1.0);\\n\\n vec2 screen = (proj.xy / abs(proj.w) + 1.0) * 0.5 * viewport.zw;\\n\\n screen += offset;\\n\\n proj.xy = (screen / viewport.zw - 0.5) * 2.0 * abs(proj.w);\\n gl_Position = proj;\\n#ifdef VERTEX_COLOR\\n v_Color = a_Color;\\n#endif\\n v_Texcoord = texcoord;\\n}\\n@end\\n\\n\\n@export ecgl.labels.fragment\\n\\nuniform vec3 color : [1.0, 1.0, 1.0];\\nuniform float alpha : 1.0;\\nuniform sampler2D textureAtlas;\\nuniform vec2 uvScale: [1.0, 1.0];\\n\\n#ifdef VERTEX_COLOR\\nvarying vec4 v_Color;\\n#endif\\nvarying float v_Miter;\\n\\nvarying vec2 v_Texcoord;\\n\\nvoid main()\\n{\\n gl_FragColor = vec4(color, alpha) * texture2D(textureAtlas, v_Texcoord * uvScale);\\n#ifdef VERTEX_COLOR\\n gl_FragColor *= v_Color;\\n#endif\\n}\\n\\n@end\";","import graphicGL from '../graphicGL';\nimport SpritesGeometry from '../geometry/Sprites';\nimport labelsGLSL from '../shader/labels.glsl.js';\ngraphicGL.Shader.import(labelsGLSL);\nexport default graphicGL.Mesh.extend(function () {\n var geometry = new SpritesGeometry({\n dynamic: true\n });\n var material = new graphicGL.Material({\n shader: graphicGL.createShader('ecgl.labels'),\n transparent: true,\n depthMask: false\n });\n return {\n geometry: geometry,\n material: material,\n culling: false,\n castShadow: false,\n ignorePicking: true\n };\n});","import * as echarts from 'echarts/lib/echarts';\nimport { createTextStyle } from 'echarts/lib/label/labelStyle';\nimport graphicGL from '../../util/graphicGL';\nimport Lines3DGeometry from '../../util/geometry/Lines3D';\nimport retrieve from '../../util/retrieve';\nimport LabelsMesh from '../../util/mesh/LabelsMesh';\nvar firstNotNull = retrieve.firstNotNull;\nvar dimIndicesMap = {\n // Left to right\n x: 0,\n // Far to near\n y: 2,\n // Bottom to up\n z: 1\n};\n\nfunction Grid3DAxis(dim, linesMaterial) {\n var linesMesh = new graphicGL.Mesh({\n geometry: new Lines3DGeometry({\n useNativeLine: false\n }),\n material: linesMaterial,\n castShadow: false,\n ignorePicking: true,\n renderOrder: 2\n });\n var axisLabelsMesh = new LabelsMesh();\n axisLabelsMesh.material.depthMask = false;\n var rootNode = new graphicGL.Node();\n rootNode.add(linesMesh);\n rootNode.add(axisLabelsMesh);\n this.rootNode = rootNode;\n this.dim = dim;\n this.linesMesh = linesMesh;\n this.labelsMesh = axisLabelsMesh;\n this.axisLineCoords = null;\n this.labelElements = [];\n}\n\nvar otherDim = {\n x: 'y',\n y: 'x',\n z: 'y'\n};\n\nGrid3DAxis.prototype.update = function (grid3DModel, axisLabelSurface, api) {\n var cartesian = grid3DModel.coordinateSystem;\n var axis = cartesian.getAxis(this.dim);\n var linesGeo = this.linesMesh.geometry;\n var labelsGeo = this.labelsMesh.geometry;\n linesGeo.convertToDynamicArray(true);\n labelsGeo.convertToDynamicArray(true);\n var axisModel = axis.model;\n var extent = axis.getExtent();\n var dpr = api.getDevicePixelRatio();\n var axisLineModel = axisModel.getModel('axisLine', grid3DModel.getModel('axisLine'));\n var axisTickModel = axisModel.getModel('axisTick', grid3DModel.getModel('axisTick'));\n var axisLabelModel = axisModel.getModel('axisLabel', grid3DModel.getModel('axisLabel'));\n var axisLineColor = axisLineModel.get('lineStyle.color'); // Render axisLine\n\n if (axisLineModel.get('show')) {\n var axisLineStyleModel = axisLineModel.getModel('lineStyle');\n var p0 = [0, 0, 0];\n var p1 = [0, 0, 0];\n var idx = dimIndicesMap[axis.dim];\n p0[idx] = extent[0];\n p1[idx] = extent[1]; // Save some useful info.\n\n this.axisLineCoords = [p0, p1];\n var color = graphicGL.parseColor(axisLineColor);\n var lineWidth = firstNotNull(axisLineStyleModel.get('width'), 1.0);\n var opacity = firstNotNull(axisLineStyleModel.get('opacity'), 1.0);\n color[3] *= opacity;\n linesGeo.addLine(p0, p1, color, lineWidth * dpr);\n } // Render axis ticksCoords\n\n\n if (axisTickModel.get('show')) {\n var lineStyleModel = axisTickModel.getModel('lineStyle');\n var lineColor = graphicGL.parseColor(firstNotNull(lineStyleModel.get('color'), axisLineColor));\n var lineWidth = firstNotNull(lineStyleModel.get('width'), 1.0);\n lineColor[3] *= firstNotNull(lineStyleModel.get('opacity'), 1.0);\n var ticksCoords = axis.getTicksCoords();\n var tickLength = axisTickModel.get('length');\n\n for (var i = 0; i < ticksCoords.length; i++) {\n var tickCoord = ticksCoords[i].coord;\n var p0 = [0, 0, 0];\n var p1 = [0, 0, 0];\n var idx = dimIndicesMap[axis.dim];\n var otherIdx = dimIndicesMap[otherDim[axis.dim]]; // 0 : x, 1 : y\n\n p0[idx] = p1[idx] = tickCoord;\n p1[otherIdx] = tickLength;\n linesGeo.addLine(p0, p1, lineColor, lineWidth * dpr);\n }\n }\n\n this.labelElements = [];\n var dpr = api.getDevicePixelRatio();\n\n if (axisLabelModel.get('show')) {\n var ticksCoords = axis.getTicksCoords();\n var categoryData = axisModel.get('data');\n var labelMargin = axisLabelModel.get('margin');\n var labels = axis.getViewLabels();\n\n for (var i = 0; i < labels.length; i++) {\n var tickValue = labels[i].tickValue;\n var formattedLabel = labels[i].formattedLabel;\n var rawLabel = labels[i].rawLabel;\n var tickCoord = axis.dataToCoord(tickValue);\n var p = [0, 0, 0];\n var idx = dimIndicesMap[axis.dim];\n var otherIdx = dimIndicesMap[otherDim[axis.dim]]; // 0 : x, 1 : y\n\n p[idx] = p[idx] = tickCoord;\n p[otherIdx] = labelMargin;\n var itemTextStyleModel = axisLabelModel;\n\n if (categoryData && categoryData[tickValue] && categoryData[tickValue].textStyle) {\n itemTextStyleModel = new echarts.Model(categoryData[tickValue].textStyle, axisLabelModel, axisModel.ecModel);\n }\n\n var textColor = firstNotNull(itemTextStyleModel.get('color'), axisLineColor);\n var textEl = new echarts.graphic.Text({\n style: createTextStyle(itemTextStyleModel, {\n text: formattedLabel,\n fill: typeof textColor === 'function' ? textColor( // (1) In category axis with data zoom, tick is not the original\n // index of axis.data. So tick should not be exposed to user\n // in category axis.\n // (2) Compatible with previous version, which always returns labelStr.\n // But in interval scale labelStr is like '223,445', which maked\n // user repalce ','. So we modify it to return original val but remain\n // it as 'string' to avoid error in replacing.\n axis.type === 'category' ? rawLabel : axis.type === 'value' ? tickValue + '' : tickValue, i) : textColor,\n verticalAlign: 'top',\n align: 'left'\n })\n });\n var coords = axisLabelSurface.add(textEl);\n var rect = textEl.getBoundingRect();\n labelsGeo.addSprite(p, [rect.width * dpr, rect.height * dpr], coords);\n this.labelElements.push(textEl);\n }\n }\n\n if (axisModel.get('name')) {\n var nameTextStyleModel = axisModel.getModel('nameTextStyle');\n var p = [0, 0, 0];\n var idx = dimIndicesMap[axis.dim];\n var otherIdx = dimIndicesMap[otherDim[axis.dim]];\n var labelColor = firstNotNull(nameTextStyleModel.get('color'), axisLineColor);\n var strokeColor = nameTextStyleModel.get('borderColor');\n var lineWidth = nameTextStyleModel.get('borderWidth'); // TODO start and end\n\n p[idx] = p[idx] = (extent[0] + extent[1]) / 2;\n p[otherIdx] = axisModel.get('nameGap');\n var textEl = new echarts.graphic.Text({\n style: createTextStyle(nameTextStyleModel, {\n text: axisModel.get('name'),\n fill: labelColor,\n stroke: strokeColor,\n lineWidth: lineWidth\n })\n });\n var coords = axisLabelSurface.add(textEl);\n var rect = textEl.getBoundingRect();\n labelsGeo.addSprite(p, [rect.width * dpr, rect.height * dpr], coords);\n textEl.__idx = this.labelElements.length;\n this.nameLabelElement = textEl;\n }\n\n this.labelsMesh.material.set('textureAtlas', axisLabelSurface.getTexture());\n this.labelsMesh.material.set('uvScale', axisLabelSurface.getCoordsScale());\n linesGeo.convertToTypedArray();\n labelsGeo.convertToTypedArray();\n};\n\nGrid3DAxis.prototype.setSpriteAlign = function (textAlign, textVerticalAlign, api) {\n var dpr = api.getDevicePixelRatio();\n var labelGeo = this.labelsMesh.geometry;\n\n for (var i = 0; i < this.labelElements.length; i++) {\n var labelEl = this.labelElements[i];\n var rect = labelEl.getBoundingRect();\n labelGeo.setSpriteAlign(i, [rect.width * dpr, rect.height * dpr], textAlign, textVerticalAlign);\n } // name label\n\n\n var nameLabelEl = this.nameLabelElement;\n\n if (nameLabelEl) {\n var rect = nameLabelEl.getBoundingRect();\n labelGeo.setSpriteAlign(nameLabelEl.__idx, [rect.width * dpr, rect.height * dpr], textAlign, textVerticalAlign);\n labelGeo.dirty();\n }\n\n this.textAlign = textAlign;\n this.textVerticalAlign = textVerticalAlign;\n};\n\nexport default Grid3DAxis;","export default \"@export ecgl.lines3D.vertex\\n\\nuniform mat4 worldViewProjection : WORLDVIEWPROJECTION;\\n\\nattribute vec3 position: POSITION;\\nattribute vec4 a_Color : COLOR;\\nvarying vec4 v_Color;\\n\\nvoid main()\\n{\\n gl_Position = worldViewProjection * vec4(position, 1.0);\\n v_Color = a_Color;\\n}\\n\\n@end\\n\\n@export ecgl.lines3D.fragment\\n\\nuniform vec4 color : [1.0, 1.0, 1.0, 1.0];\\n\\nvarying vec4 v_Color;\\n\\n@import clay.util.srgb\\n\\nvoid main()\\n{\\n#ifdef SRGB_DECODE\\n gl_FragColor = sRGBToLinear(color * v_Color);\\n#else\\n gl_FragColor = color * v_Color;\\n#endif\\n}\\n@end\\n\\n\\n\\n@export ecgl.lines3D.clipNear\\n\\nvec4 clipNear(vec4 p1, vec4 p2) {\\n float n = (p1.w - near) / (p1.w - p2.w);\\n return vec4(mix(p1.xy, p2.xy, n), -near, near);\\n}\\n\\n@end\\n\\n@export ecgl.lines3D.expandLine\\n#ifdef VERTEX_ANIMATION\\n vec4 prevProj = worldViewProjection * vec4(mix(prevPositionPrev, positionPrev, percent), 1.0);\\n vec4 currProj = worldViewProjection * vec4(mix(prevPosition, position, percent), 1.0);\\n vec4 nextProj = worldViewProjection * vec4(mix(prevPositionNext, positionNext, percent), 1.0);\\n#else\\n vec4 prevProj = worldViewProjection * vec4(positionPrev, 1.0);\\n vec4 currProj = worldViewProjection * vec4(position, 1.0);\\n vec4 nextProj = worldViewProjection * vec4(positionNext, 1.0);\\n#endif\\n\\n if (currProj.w < 0.0) {\\n if (nextProj.w > 0.0) {\\n currProj = clipNear(currProj, nextProj);\\n }\\n else if (prevProj.w > 0.0) {\\n currProj = clipNear(currProj, prevProj);\\n }\\n }\\n\\n vec2 prevScreen = (prevProj.xy / abs(prevProj.w) + 1.0) * 0.5 * viewport.zw;\\n vec2 currScreen = (currProj.xy / abs(currProj.w) + 1.0) * 0.5 * viewport.zw;\\n vec2 nextScreen = (nextProj.xy / abs(nextProj.w) + 1.0) * 0.5 * viewport.zw;\\n\\n vec2 dir;\\n float len = offset;\\n if (position == positionPrev) {\\n dir = normalize(nextScreen - currScreen);\\n }\\n else if (position == positionNext) {\\n dir = normalize(currScreen - prevScreen);\\n }\\n else {\\n vec2 dirA = normalize(currScreen - prevScreen);\\n vec2 dirB = normalize(nextScreen - currScreen);\\n\\n vec2 tanget = normalize(dirA + dirB);\\n\\n float miter = 1.0 / max(dot(tanget, dirA), 0.5);\\n len *= miter;\\n dir = tanget;\\n }\\n\\n dir = vec2(-dir.y, dir.x) * len;\\n currScreen += dir;\\n\\n currProj.xy = (currScreen / viewport.zw - 0.5) * 2.0 * abs(currProj.w);\\n@end\\n\\n\\n@export ecgl.meshLines3D.vertex\\n\\nattribute vec3 position: POSITION;\\nattribute vec3 positionPrev;\\nattribute vec3 positionNext;\\nattribute float offset;\\nattribute vec4 a_Color : COLOR;\\n\\n#ifdef VERTEX_ANIMATION\\nattribute vec3 prevPosition;\\nattribute vec3 prevPositionPrev;\\nattribute vec3 prevPositionNext;\\nuniform float percent : 1.0;\\n#endif\\n\\nuniform mat4 worldViewProjection : WORLDVIEWPROJECTION;\\nuniform vec4 viewport : VIEWPORT;\\nuniform float near : NEAR;\\n\\nvarying vec4 v_Color;\\n\\n@import ecgl.common.wireframe.vertexHeader\\n\\n@import ecgl.lines3D.clipNear\\n\\nvoid main()\\n{\\n @import ecgl.lines3D.expandLine\\n\\n gl_Position = currProj;\\n\\n v_Color = a_Color;\\n\\n @import ecgl.common.wireframe.vertexMain\\n}\\n@end\\n\\n\\n@export ecgl.meshLines3D.fragment\\n\\nuniform vec4 color : [1.0, 1.0, 1.0, 1.0];\\n\\nvarying vec4 v_Color;\\n\\n@import ecgl.common.wireframe.fragmentHeader\\n\\n@import clay.util.srgb\\n\\nvoid main()\\n{\\n#ifdef SRGB_DECODE\\n gl_FragColor = sRGBToLinear(color * v_Color);\\n#else\\n gl_FragColor = color * v_Color;\\n#endif\\n\\n @import ecgl.common.wireframe.fragmentMain\\n}\\n\\n@end\";","// TODO orthographic camera\nimport * as echarts from 'echarts/lib/echarts';\nimport { createTextStyle } from 'echarts/lib/label/labelStyle';\nimport graphicGL from '../../util/graphicGL';\nimport OrbitControl from '../../util/OrbitControl';\nimport Lines3DGeometry from '../../util/geometry/Lines3D';\nimport retrieve from '../../util/retrieve';\nvar firstNotNull = retrieve.firstNotNull;\nimport ZRTextureAtlasSurface from '../../util/ZRTextureAtlasSurface';\nimport SceneHelper from '../common/SceneHelper';\nimport Grid3DFace from './Grid3DFace';\nimport Grid3DAxis from './Grid3DAxis';\nimport LabelsMesh from '../../util/mesh/LabelsMesh';\nimport lines3DGLSL from '../../util/shader/lines3D.glsl.js';\ngraphicGL.Shader.import(lines3DGLSL);\nvar dimIndicesMap = {\n // Left to right\n x: 0,\n // Far to near\n y: 2,\n // Bottom to up\n z: 1\n};\nexport default echarts.ComponentView.extend({\n type: 'grid3D',\n __ecgl__: true,\n init: function (ecModel, api) {\n var FACES = [// planeDim0, planeDim1, offsetDim, dir on dim3 axis(gl), plane.\n ['y', 'z', 'x', -1, 'left'], ['y', 'z', 'x', 1, 'right'], ['x', 'y', 'z', -1, 'bottom'], ['x', 'y', 'z', 1, 'top'], ['x', 'z', 'y', -1, 'far'], ['x', 'z', 'y', 1, 'near']];\n var DIMS = ['x', 'y', 'z'];\n var quadsMaterial = new graphicGL.Material({\n // transparent: true,\n shader: graphicGL.createShader('ecgl.color'),\n depthMask: false,\n transparent: true\n });\n var linesMaterial = new graphicGL.Material({\n // transparent: true,\n shader: graphicGL.createShader('ecgl.meshLines3D'),\n depthMask: false,\n transparent: true\n });\n quadsMaterial.define('fragment', 'DOUBLE_SIDED');\n quadsMaterial.define('both', 'VERTEX_COLOR');\n this.groupGL = new graphicGL.Node();\n this._control = new OrbitControl({\n zr: api.getZr()\n });\n\n this._control.init(); // Save mesh and other infos for each face.\n\n\n this._faces = FACES.map(function (faceInfo) {\n var face = new Grid3DFace(faceInfo, linesMaterial, quadsMaterial);\n this.groupGL.add(face.rootNode);\n return face;\n }, this); // Save mesh and other infos for each axis.\n\n this._axes = DIMS.map(function (dim) {\n var axis = new Grid3DAxis(dim, linesMaterial);\n this.groupGL.add(axis.rootNode);\n return axis;\n }, this);\n var dpr = api.getDevicePixelRatio(); // Texture surface for label.\n\n this._axisLabelSurface = new ZRTextureAtlasSurface({\n width: 256,\n height: 256,\n devicePixelRatio: dpr\n });\n\n this._axisLabelSurface.onupdate = function () {\n api.getZr().refresh();\n };\n\n this._axisPointerLineMesh = new graphicGL.Mesh({\n geometry: new Lines3DGeometry({\n useNativeLine: false\n }),\n material: linesMaterial,\n castShadow: false,\n // PENDING\n ignorePicking: true,\n renderOrder: 3\n });\n this.groupGL.add(this._axisPointerLineMesh);\n this._axisPointerLabelsSurface = new ZRTextureAtlasSurface({\n width: 128,\n height: 128,\n devicePixelRatio: dpr\n });\n this._axisPointerLabelsMesh = new LabelsMesh({\n ignorePicking: true,\n renderOrder: 4,\n castShadow: false\n });\n\n this._axisPointerLabelsMesh.material.set('textureAtlas', this._axisPointerLabelsSurface.getTexture());\n\n this.groupGL.add(this._axisPointerLabelsMesh);\n this._lightRoot = new graphicGL.Node();\n this._sceneHelper = new SceneHelper();\n\n this._sceneHelper.initLight(this._lightRoot);\n },\n render: function (grid3DModel, ecModel, api) {\n this._model = grid3DModel;\n this._api = api;\n var cartesian = grid3DModel.coordinateSystem; // Always have light.\n\n cartesian.viewGL.add(this._lightRoot);\n\n if (grid3DModel.get('show')) {\n cartesian.viewGL.add(this.groupGL);\n } else {\n cartesian.viewGL.remove(this.groupGL);\n } // cartesian.viewGL.setCameraType(grid3DModel.get('viewControl.projection'));\n\n\n var control = this._control;\n control.setViewGL(cartesian.viewGL);\n var viewControlModel = grid3DModel.getModel('viewControl');\n control.setFromViewControlModel(viewControlModel, 0);\n\n this._axisLabelSurface.clear();\n\n control.off('update');\n\n if (grid3DModel.get('show')) {\n this._faces.forEach(function (face) {\n face.update(grid3DModel, ecModel, api);\n }, this);\n\n this._axes.forEach(function (axis) {\n axis.update(grid3DModel, this._axisLabelSurface, api);\n }, this);\n }\n\n control.on('update', this._onCameraChange.bind(this, grid3DModel, api), this);\n\n this._sceneHelper.setScene(cartesian.viewGL.scene);\n\n this._sceneHelper.updateLight(grid3DModel); // Set post effect\n\n\n cartesian.viewGL.setPostEffect(grid3DModel.getModel('postEffect'), api);\n cartesian.viewGL.setTemporalSuperSampling(grid3DModel.getModel('temporalSuperSampling'));\n\n this._initMouseHandler(grid3DModel);\n },\n afterRender: function (grid3DModel, ecModel, api, layerGL) {\n // Create ambient cubemap after render because we need to know the renderer.\n // TODO\n var renderer = layerGL.renderer;\n\n this._sceneHelper.updateAmbientCubemap(renderer, grid3DModel, api);\n\n this._sceneHelper.updateSkybox(renderer, grid3DModel, api);\n },\n\n /**\n * showAxisPointer will be triggered by action.\n */\n showAxisPointer: function (grid3dModel, ecModel, api, payload) {\n this._doShowAxisPointer();\n\n this._updateAxisPointer(payload.value);\n },\n\n /**\n * hideAxisPointer will be triggered by action.\n */\n hideAxisPointer: function (grid3dModel, ecModel, api, payload) {\n this._doHideAxisPointer();\n },\n _initMouseHandler: function (grid3DModel) {\n var cartesian = grid3DModel.coordinateSystem;\n var viewGL = cartesian.viewGL; // TODO xAxis3D.axisPointer.show ?\n\n if (grid3DModel.get('show') && grid3DModel.get('axisPointer.show')) {\n viewGL.on('mousemove', this._updateAxisPointerOnMousePosition, this);\n } else {\n viewGL.off('mousemove', this._updateAxisPointerOnMousePosition);\n }\n },\n\n /**\n * Try find and show axisPointer on the intersect point\n * of mouse ray with grid plane.\n */\n _updateAxisPointerOnMousePosition: function (e) {\n // Ignore if mouse is on the element.\n if (e.target) {\n return;\n }\n\n var grid3DModel = this._model;\n var cartesian = grid3DModel.coordinateSystem;\n var viewGL = cartesian.viewGL;\n var ray = viewGL.castRay(e.offsetX, e.offsetY, new graphicGL.Ray());\n var nearestIntersectPoint;\n\n for (var i = 0; i < this._faces.length; i++) {\n var face = this._faces[i];\n\n if (face.rootNode.invisible) {\n continue;\n } // Plane is not face the camera. flip it\n\n\n if (face.plane.normal.dot(viewGL.camera.worldTransform.z) < 0) {\n face.plane.normal.negate();\n }\n\n var point = ray.intersectPlane(face.plane);\n\n if (!point) {\n continue;\n }\n\n var axis0 = cartesian.getAxis(face.faceInfo[0]);\n var axis1 = cartesian.getAxis(face.faceInfo[1]);\n var idx0 = dimIndicesMap[face.faceInfo[0]];\n var idx1 = dimIndicesMap[face.faceInfo[1]];\n\n if (axis0.contain(point.array[idx0]) && axis1.contain(point.array[idx1])) {\n nearestIntersectPoint = point;\n }\n }\n\n if (nearestIntersectPoint) {\n var data = cartesian.pointToData(nearestIntersectPoint.array, [], true);\n\n this._updateAxisPointer(data);\n\n this._doShowAxisPointer();\n } else {\n this._doHideAxisPointer();\n }\n },\n _onCameraChange: function (grid3DModel, api) {\n if (grid3DModel.get('show')) {\n this._updateFaceVisibility();\n\n this._updateAxisLinePosition();\n }\n\n var control = this._control;\n api.dispatchAction({\n type: 'grid3DChangeCamera',\n alpha: control.getAlpha(),\n beta: control.getBeta(),\n distance: control.getDistance(),\n center: control.getCenter(),\n from: this.uid,\n grid3DId: grid3DModel.id\n });\n },\n\n /**\n * Update visibility of each face when camera view changed, front face will be invisible.\n * @private\n */\n _updateFaceVisibility: function () {\n var camera = this._control.getCamera();\n\n var viewSpacePos = new graphicGL.Vector3();\n camera.update();\n\n for (var idx = 0; idx < this._faces.length / 2; idx++) {\n var depths = [];\n\n for (var k = 0; k < 2; k++) {\n var face = this._faces[idx * 2 + k];\n face.rootNode.getWorldPosition(viewSpacePos);\n viewSpacePos.transformMat4(camera.viewMatrix);\n depths[k] = viewSpacePos.z;\n } // Set the front face invisible\n\n\n var frontIndex = depths[0] > depths[1] ? 0 : 1;\n var frontFace = this._faces[idx * 2 + frontIndex];\n var backFace = this._faces[idx * 2 + 1 - frontIndex]; // Update rotation.\n\n frontFace.rootNode.invisible = true;\n backFace.rootNode.invisible = false;\n }\n },\n\n /**\n * Update axis line position when camera view changed.\n * @private\n */\n _updateAxisLinePosition: function () {\n // Put xAxis, yAxis on x, y visible plane.\n // Put zAxis on the left.\n // TODO\n var cartesian = this._model.coordinateSystem;\n var xAxis = cartesian.getAxis('x');\n var yAxis = cartesian.getAxis('y');\n var zAxis = cartesian.getAxis('z');\n var top = zAxis.getExtentMax();\n var bottom = zAxis.getExtentMin();\n var left = xAxis.getExtentMin();\n var right = xAxis.getExtentMax();\n var near = yAxis.getExtentMax();\n var far = yAxis.getExtentMin();\n var xAxisNode = this._axes[0].rootNode;\n var yAxisNode = this._axes[1].rootNode;\n var zAxisNode = this._axes[2].rootNode;\n var faces = this._faces; // Notice: in cartesian up axis is z, but in webgl up axis is y.\n\n var xAxisZOffset = faces[4].rootNode.invisible ? far : near;\n var xAxisYOffset = faces[2].rootNode.invisible ? top : bottom;\n var yAxisXOffset = faces[0].rootNode.invisible ? left : right;\n var yAxisYOffset = faces[2].rootNode.invisible ? top : bottom;\n var zAxisXOffset = faces[0].rootNode.invisible ? right : left;\n var zAxisZOffset = faces[4].rootNode.invisible ? far : near;\n xAxisNode.rotation.identity();\n yAxisNode.rotation.identity();\n zAxisNode.rotation.identity();\n\n if (faces[4].rootNode.invisible) {\n this._axes[0].flipped = true;\n xAxisNode.rotation.rotateX(Math.PI);\n }\n\n if (faces[0].rootNode.invisible) {\n this._axes[1].flipped = true;\n yAxisNode.rotation.rotateZ(Math.PI);\n }\n\n if (faces[4].rootNode.invisible) {\n this._axes[2].flipped = true;\n zAxisNode.rotation.rotateY(Math.PI);\n }\n\n xAxisNode.position.set(0, xAxisYOffset, xAxisZOffset);\n yAxisNode.position.set(yAxisXOffset, yAxisYOffset, 0); // Actually z\n\n zAxisNode.position.set(zAxisXOffset, 0, zAxisZOffset); // Actually y\n\n xAxisNode.update();\n yAxisNode.update();\n zAxisNode.update();\n\n this._updateAxisLabelAlign();\n },\n\n /**\n * Update label align on axis when axisLine position changed.\n * @private\n */\n _updateAxisLabelAlign: function () {\n // var cartesian = this._model.coordinateSystem;\n var camera = this._control.getCamera();\n\n var coords = [new graphicGL.Vector4(), new graphicGL.Vector4()];\n var center = new graphicGL.Vector4();\n this.groupGL.getWorldPosition(center);\n center.w = 1.0;\n center.transformMat4(camera.viewMatrix).transformMat4(camera.projectionMatrix);\n center.x /= center.w;\n center.y /= center.w;\n\n this._axes.forEach(function (axisInfo) {\n var lineCoords = axisInfo.axisLineCoords;\n var labelGeo = axisInfo.labelsMesh.geometry;\n\n for (var i = 0; i < coords.length; i++) {\n coords[i].setArray(lineCoords[i]);\n coords[i].w = 1.0;\n coords[i].transformMat4(axisInfo.rootNode.worldTransform).transformMat4(camera.viewMatrix).transformMat4(camera.projectionMatrix);\n coords[i].x /= coords[i].w;\n coords[i].y /= coords[i].w;\n }\n\n var dx = coords[1].x - coords[0].x;\n var dy = coords[1].y - coords[0].y;\n var cx = (coords[1].x + coords[0].x) / 2;\n var cy = (coords[1].y + coords[0].y) / 2;\n var textAlign;\n var verticalAlign;\n\n if (Math.abs(dy / dx) < 0.5) {\n textAlign = 'center';\n verticalAlign = cy > center.y ? 'bottom' : 'top';\n } else {\n verticalAlign = 'middle';\n textAlign = cx > center.x ? 'left' : 'right';\n } // axis labels\n\n\n axisInfo.setSpriteAlign(textAlign, verticalAlign, this._api);\n }, this);\n },\n _doShowAxisPointer: function () {\n if (!this._axisPointerLineMesh.invisible) {\n return;\n }\n\n this._axisPointerLineMesh.invisible = false;\n this._axisPointerLabelsMesh.invisible = false;\n\n this._api.getZr().refresh();\n },\n _doHideAxisPointer: function () {\n if (this._axisPointerLineMesh.invisible) {\n return;\n }\n\n this._axisPointerLineMesh.invisible = true;\n this._axisPointerLabelsMesh.invisible = true;\n\n this._api.getZr().refresh();\n },\n\n /**\n * @private updateAxisPointer.\n */\n _updateAxisPointer: function (data) {\n var cartesian = this._model.coordinateSystem;\n var point = cartesian.dataToPoint(data);\n var axisPointerLineMesh = this._axisPointerLineMesh;\n var linesGeo = axisPointerLineMesh.geometry;\n\n var axisPointerParentModel = this._model.getModel('axisPointer');\n\n var dpr = this._api.getDevicePixelRatio();\n\n linesGeo.convertToDynamicArray(true);\n\n function ifShowAxisPointer(axis) {\n return retrieve.firstNotNull(axis.model.get('axisPointer.show'), axisPointerParentModel.get('show'));\n }\n\n function getAxisColorAndLineWidth(axis) {\n var axisPointerModel = axis.model.getModel('axisPointer', axisPointerParentModel);\n var lineStyleModel = axisPointerModel.getModel('lineStyle');\n var color = graphicGL.parseColor(lineStyleModel.get('color'));\n var lineWidth = firstNotNull(lineStyleModel.get('width'), 1);\n var opacity = firstNotNull(lineStyleModel.get('opacity'), 1);\n color[3] *= opacity;\n return {\n color: color,\n lineWidth: lineWidth\n };\n }\n\n for (var k = 0; k < this._faces.length; k++) {\n var face = this._faces[k];\n\n if (face.rootNode.invisible) {\n continue;\n }\n\n var faceInfo = face.faceInfo;\n var otherCoord = faceInfo[3] < 0 ? cartesian.getAxis(faceInfo[2]).getExtentMin() : cartesian.getAxis(faceInfo[2]).getExtentMax();\n var otherDimIdx = dimIndicesMap[faceInfo[2]]; // Line on face.\n\n for (var i = 0; i < 2; i++) {\n var dim = faceInfo[i];\n var faceOtherDim = faceInfo[1 - i];\n var axis = cartesian.getAxis(dim);\n var faceOtherAxis = cartesian.getAxis(faceOtherDim);\n\n if (!ifShowAxisPointer(axis)) {\n continue;\n }\n\n var p0 = [0, 0, 0];\n var p1 = [0, 0, 0];\n var dimIdx = dimIndicesMap[dim];\n var faceOtherDimIdx = dimIndicesMap[faceOtherDim];\n p0[dimIdx] = p1[dimIdx] = point[dimIdx];\n p0[otherDimIdx] = p1[otherDimIdx] = otherCoord;\n p0[faceOtherDimIdx] = faceOtherAxis.getExtentMin();\n p1[faceOtherDimIdx] = faceOtherAxis.getExtentMax();\n var colorAndLineWidth = getAxisColorAndLineWidth(axis);\n linesGeo.addLine(p0, p1, colorAndLineWidth.color, colorAndLineWidth.lineWidth * dpr);\n } // Project line.\n\n\n if (ifShowAxisPointer(cartesian.getAxis(faceInfo[2]))) {\n var p0 = point.slice();\n var p1 = point.slice();\n p1[otherDimIdx] = otherCoord;\n var colorAndLineWidth = getAxisColorAndLineWidth(cartesian.getAxis(faceInfo[2]));\n linesGeo.addLine(p0, p1, colorAndLineWidth.color, colorAndLineWidth.lineWidth * dpr);\n }\n }\n\n linesGeo.convertToTypedArray();\n\n this._updateAxisPointerLabelsMesh(data);\n\n this._api.getZr().refresh();\n },\n _updateAxisPointerLabelsMesh: function (data) {\n var grid3dModel = this._model;\n var axisPointerLabelsMesh = this._axisPointerLabelsMesh;\n var axisPointerLabelsSurface = this._axisPointerLabelsSurface;\n var cartesian = grid3dModel.coordinateSystem;\n var axisPointerParentModel = grid3dModel.getModel('axisPointer');\n axisPointerLabelsMesh.geometry.convertToDynamicArray(true);\n axisPointerLabelsSurface.clear();\n var otherDim = {\n x: 'y',\n y: 'x',\n z: 'y'\n };\n\n this._axes.forEach(function (axisInfo, idx) {\n var axis = cartesian.getAxis(axisInfo.dim);\n var axisModel = axis.model;\n var axisPointerModel = axisModel.getModel('axisPointer', axisPointerParentModel);\n var labelModel = axisPointerModel.getModel('label');\n var lineColor = axisPointerModel.get('lineStyle.color');\n\n if (!labelModel.get('show') || !axisPointerModel.get('show')) {\n return;\n }\n\n var val = data[idx];\n var formatter = labelModel.get('formatter');\n var text = axis.scale.getLabel({\n value: val\n });\n\n if (formatter != null) {\n text = formatter(text, data);\n } else {\n if (axis.scale.type === 'interval' || axis.scale.type === 'log') {\n var precision = echarts.number.getPrecisionSafe(axis.scale.getTicks()[0]);\n text = val.toFixed(precision + 2);\n }\n }\n\n var labelColor = labelModel.get('color');\n var textEl = new echarts.graphic.Text({\n style: createTextStyle(labelModel, {\n text: text,\n fill: labelColor || lineColor,\n align: 'left',\n verticalAlign: 'top'\n })\n });\n var coords = axisPointerLabelsSurface.add(textEl);\n var rect = textEl.getBoundingRect();\n\n var dpr = this._api.getDevicePixelRatio();\n\n var pos = axisInfo.rootNode.position.toArray();\n var otherIdx = dimIndicesMap[otherDim[axisInfo.dim]];\n pos[otherIdx] += (axisInfo.flipped ? -1 : 1) * labelModel.get('margin');\n pos[dimIndicesMap[axisInfo.dim]] = axis.dataToCoord(data[idx]);\n axisPointerLabelsMesh.geometry.addSprite(pos, [rect.width * dpr, rect.height * dpr], coords, axisInfo.textAlign, axisInfo.textVerticalAlign);\n }, this);\n\n axisPointerLabelsSurface.getZr().refreshImmediately();\n axisPointerLabelsMesh.material.set('uvScale', axisPointerLabelsSurface.getCoordsScale());\n axisPointerLabelsMesh.geometry.convertToTypedArray();\n },\n dispose: function () {\n this.groupGL.removeAll();\n\n this._control.dispose();\n\n this._axisLabelSurface.dispose();\n\n this._axisPointerLabelsSurface.dispose();\n }\n});","import * as echarts from 'echarts/lib/echarts';\nimport Cartesian from 'echarts/lib/coord/cartesian/Cartesian';\n\nfunction Cartesian3D(name) {\n Cartesian.call(this, name);\n this.type = 'cartesian3D';\n this.dimensions = ['x', 'y', 'z'];\n this.size = [0, 0, 0];\n}\n\nCartesian3D.prototype = {\n constructor: Cartesian3D,\n model: null,\n containPoint: function (point) {\n return this.getAxis('x').contain(point[0]) && this.getAxis('y').contain(point[2]) && this.getAxis('z').contain(point[1]);\n },\n containData: function (data) {\n return this.getAxis('x').containData(data[0]) && this.getAxis('y').containData(data[1]) && this.getAxis('z').containData(data[2]);\n },\n dataToPoint: function (data, out, clamp) {\n out = out || [];\n out[0] = this.getAxis('x').dataToCoord(data[0], clamp);\n out[2] = this.getAxis('y').dataToCoord(data[1], clamp);\n out[1] = this.getAxis('z').dataToCoord(data[2], clamp);\n return out;\n },\n pointToData: function (point, out, clamp) {\n out = out || [];\n out[0] = this.getAxis('x').coordToData(point[0], clamp);\n out[1] = this.getAxis('y').coordToData(point[2], clamp);\n out[2] = this.getAxis('z').coordToData(point[1], clamp);\n return out;\n }\n};\necharts.util.inherits(Cartesian3D, Cartesian);\nexport default Cartesian3D;","import * as echarts from 'echarts/lib/echarts';\n\nfunction Axis3D(dim, scale, extent) {\n echarts.Axis.call(this, dim, scale, extent);\n}\n\nAxis3D.prototype = {\n constructor: Axis3D,\n getExtentMin: function () {\n var extent = this._extent;\n return Math.min(extent[0], extent[1]);\n },\n getExtentMax: function () {\n var extent = this._extent;\n return Math.max(extent[0], extent[1]);\n },\n calculateCategoryInterval: function () {\n // TODO consider label length\n return Math.floor(this.scale.count() / 8);\n }\n};\necharts.util.inherits(Axis3D, echarts.Axis);\nexport default Axis3D;","import Texture2D from '../Texture2D';\nimport glenum from '../core/glenum';\nimport util from '../core/util';\n\nvar TexturePool = function () {\n\n this._pool = {};\n\n this._allocatedTextures = [];\n};\n\nTexturePool.prototype = {\n\n constructor: TexturePool,\n\n get: function (parameters) {\n var key = generateKey(parameters);\n if (!this._pool.hasOwnProperty(key)) {\n this._pool[key] = [];\n }\n var list = this._pool[key];\n if (!list.length) {\n var texture = new Texture2D(parameters);\n this._allocatedTextures.push(texture);\n return texture;\n }\n return list.pop();\n },\n\n put: function (texture) {\n var key = generateKey(texture);\n if (!this._pool.hasOwnProperty(key)) {\n this._pool[key] = [];\n }\n var list = this._pool[key];\n list.push(texture);\n },\n\n clear: function (renderer) {\n for (var i = 0; i < this._allocatedTextures.length; i++) {\n this._allocatedTextures[i].dispose(renderer);\n }\n this._pool = {};\n this._allocatedTextures = [];\n }\n};\n\nvar defaultParams = {\n width: 512,\n height: 512,\n type: glenum.UNSIGNED_BYTE,\n format: glenum.RGBA,\n wrapS: glenum.CLAMP_TO_EDGE,\n wrapT: glenum.CLAMP_TO_EDGE,\n minFilter: glenum.LINEAR_MIPMAP_LINEAR,\n magFilter: glenum.LINEAR,\n useMipmap: true,\n anisotropic: 1,\n flipY: true,\n unpackAlignment: 4,\n premultiplyAlpha: false\n};\n\nvar defaultParamPropList = Object.keys(defaultParams);\n\nfunction generateKey(parameters) {\n util.defaultsWithPropList(parameters, defaultParams, defaultParamPropList);\n fallBack(parameters);\n\n var key = '';\n for (var i = 0; i < defaultParamPropList.length; i++) {\n var name = defaultParamPropList[i];\n var chunk = parameters[name].toString();\n key += chunk;\n }\n return key;\n}\n\nfunction fallBack(target) {\n\n var IPOT = isPowerOfTwo(target.width, target.height);\n\n if (target.format === glenum.DEPTH_COMPONENT) {\n target.useMipmap = false;\n }\n\n if (!IPOT || !target.useMipmap) {\n if (target.minFilter == glenum.NEAREST_MIPMAP_NEAREST ||\n target.minFilter == glenum.NEAREST_MIPMAP_LINEAR) {\n target.minFilter = glenum.NEAREST;\n } else if (\n target.minFilter == glenum.LINEAR_MIPMAP_LINEAR ||\n target.minFilter == glenum.LINEAR_MIPMAP_NEAREST\n ) {\n target.minFilter = glenum.LINEAR;\n }\n }\n if (!IPOT) {\n target.wrapS = glenum.CLAMP_TO_EDGE;\n target.wrapT = glenum.CLAMP_TO_EDGE;\n }\n}\n\nfunction isPowerOfTwo(width, height) {\n return (width & (width-1)) === 0 &&\n (height & (height-1)) === 0;\n}\n\nexport default TexturePool;\n","export default \"@export clay.sm.depth.vertex\\nuniform mat4 worldViewProjection : WORLDVIEWPROJECTION;\\nattribute vec3 position : POSITION;\\nattribute vec2 texcoord : TEXCOORD_0;\\nuniform vec2 uvRepeat = vec2(1.0, 1.0);\\nuniform vec2 uvOffset = vec2(0.0, 0.0);\\n@import clay.chunk.skinning_header\\n@import clay.chunk.instancing_header\\nvarying vec4 v_ViewPosition;\\nvarying vec2 v_Texcoord;\\nvoid main(){\\n vec4 P = vec4(position, 1.0);\\n#ifdef SKINNING\\n @import clay.chunk.skin_matrix\\n P = skinMatrixWS * P;\\n#endif\\n#ifdef INSTANCING\\n @import clay.chunk.instancing_matrix\\n P = instanceMat * P;\\n#endif\\n v_ViewPosition = worldViewProjection * P;\\n gl_Position = v_ViewPosition;\\n v_Texcoord = texcoord * uvRepeat + uvOffset;\\n}\\n@end\\n@export clay.sm.depth.fragment\\nvarying vec4 v_ViewPosition;\\nvarying vec2 v_Texcoord;\\nuniform float bias : 0.001;\\nuniform float slopeScale : 1.0;\\nuniform sampler2D alphaMap;\\nuniform float alphaCutoff: 0.0;\\n@import clay.util.encode_float\\nvoid main(){\\n float depth = v_ViewPosition.z / v_ViewPosition.w;\\n if (alphaCutoff > 0.0) {\\n if (texture2D(alphaMap, v_Texcoord).a <= alphaCutoff) {\\n discard;\\n }\\n }\\n#ifdef USE_VSM\\n depth = depth * 0.5 + 0.5;\\n float moment1 = depth;\\n float moment2 = depth * depth;\\n #ifdef SUPPORT_STANDARD_DERIVATIVES\\n float dx = dFdx(depth);\\n float dy = dFdy(depth);\\n moment2 += 0.25*(dx*dx+dy*dy);\\n #endif\\n gl_FragColor = vec4(moment1, moment2, 0.0, 1.0);\\n#else\\n #ifdef SUPPORT_STANDARD_DERIVATIVES\\n float dx = dFdx(depth);\\n float dy = dFdy(depth);\\n depth += sqrt(dx*dx + dy*dy) * slopeScale + bias;\\n #else\\n depth += bias;\\n #endif\\n gl_FragColor = encodeFloat(depth * 0.5 + 0.5);\\n#endif\\n}\\n@end\\n@export clay.sm.debug_depth\\nuniform sampler2D depthMap;\\nvarying vec2 v_Texcoord;\\n@import clay.util.decode_float\\nvoid main() {\\n vec4 tex = texture2D(depthMap, v_Texcoord);\\n#ifdef USE_VSM\\n gl_FragColor = vec4(tex.rgb, 1.0);\\n#else\\n float depth = decodeFloat(tex);\\n gl_FragColor = vec4(depth, depth, depth, 1.0);\\n#endif\\n}\\n@end\\n@export clay.sm.distance.vertex\\nuniform mat4 worldViewProjection : WORLDVIEWPROJECTION;\\nuniform mat4 world : WORLD;\\nattribute vec3 position : POSITION;\\n@import clay.chunk.skinning_header\\nvarying vec3 v_WorldPosition;\\nvoid main (){\\n vec4 P = vec4(position, 1.0);\\n#ifdef SKINNING\\n @import clay.chunk.skin_matrix\\n P = skinMatrixWS * P;\\n#endif\\n#ifdef INSTANCING\\n @import clay.chunk.instancing_matrix\\n P = instanceMat * P;\\n#endif\\n gl_Position = worldViewProjection * P;\\n v_WorldPosition = (world * P).xyz;\\n}\\n@end\\n@export clay.sm.distance.fragment\\nuniform vec3 lightPosition;\\nuniform float range : 100;\\nvarying vec3 v_WorldPosition;\\n@import clay.util.encode_float\\nvoid main(){\\n float dist = distance(lightPosition, v_WorldPosition);\\n#ifdef USE_VSM\\n gl_FragColor = vec4(dist, dist * dist, 0.0, 0.0);\\n#else\\n dist = dist / range;\\n gl_FragColor = encodeFloat(dist);\\n#endif\\n}\\n@end\\n@export clay.plugin.shadow_map_common\\n@import clay.util.decode_float\\nfloat tapShadowMap(sampler2D map, vec2 uv, float z){\\n vec4 tex = texture2D(map, uv);\\n return step(z, decodeFloat(tex) * 2.0 - 1.0);\\n}\\nfloat pcf(sampler2D map, vec2 uv, float z, float textureSize, vec2 scale) {\\n float shadowContrib = tapShadowMap(map, uv, z);\\n vec2 offset = vec2(1.0 / textureSize) * scale;\\n#ifdef PCF_KERNEL_SIZE\\n for (int _idx_ = 0; _idx_ < PCF_KERNEL_SIZE; _idx_++) {{\\n shadowContrib += tapShadowMap(map, uv + offset * pcfKernel[_idx_], z);\\n }}\\n return shadowContrib / float(PCF_KERNEL_SIZE + 1);\\n#else\\n shadowContrib += tapShadowMap(map, uv+vec2(offset.x, 0.0), z);\\n shadowContrib += tapShadowMap(map, uv+vec2(offset.x, offset.y), z);\\n shadowContrib += tapShadowMap(map, uv+vec2(-offset.x, offset.y), z);\\n shadowContrib += tapShadowMap(map, uv+vec2(0.0, offset.y), z);\\n shadowContrib += tapShadowMap(map, uv+vec2(-offset.x, 0.0), z);\\n shadowContrib += tapShadowMap(map, uv+vec2(-offset.x, -offset.y), z);\\n shadowContrib += tapShadowMap(map, uv+vec2(offset.x, -offset.y), z);\\n shadowContrib += tapShadowMap(map, uv+vec2(0.0, -offset.y), z);\\n return shadowContrib / 9.0;\\n#endif\\n}\\nfloat pcf(sampler2D map, vec2 uv, float z, float textureSize) {\\n return pcf(map, uv, z, textureSize, vec2(1.0));\\n}\\nfloat chebyshevUpperBound(vec2 moments, float z){\\n float p = 0.0;\\n z = z * 0.5 + 0.5;\\n if (z <= moments.x) {\\n p = 1.0;\\n }\\n float variance = moments.y - moments.x * moments.x;\\n variance = max(variance, 0.0000001);\\n float mD = moments.x - z;\\n float pMax = variance / (variance + mD * mD);\\n pMax = clamp((pMax-0.4)/(1.0-0.4), 0.0, 1.0);\\n return max(p, pMax);\\n}\\nfloat computeShadowContrib(\\n sampler2D map, mat4 lightVPM, vec3 position, float textureSize, vec2 scale, vec2 offset\\n) {\\n vec4 posInLightSpace = lightVPM * vec4(position, 1.0);\\n posInLightSpace.xyz /= posInLightSpace.w;\\n float z = posInLightSpace.z;\\n if(all(greaterThan(posInLightSpace.xyz, vec3(-0.99, -0.99, -1.0))) &&\\n all(lessThan(posInLightSpace.xyz, vec3(0.99, 0.99, 1.0)))){\\n vec2 uv = (posInLightSpace.xy+1.0) / 2.0;\\n #ifdef USE_VSM\\n vec2 moments = texture2D(map, uv * scale + offset).xy;\\n return chebyshevUpperBound(moments, z);\\n #else\\n return pcf(map, uv * scale + offset, z, textureSize, scale);\\n #endif\\n }\\n return 1.0;\\n}\\nfloat computeShadowContrib(sampler2D map, mat4 lightVPM, vec3 position, float textureSize) {\\n return computeShadowContrib(map, lightVPM, position, textureSize, vec2(1.0), vec2(0.0));\\n}\\nfloat computeShadowContribOmni(samplerCube map, vec3 direction, float range)\\n{\\n float dist = length(direction);\\n vec4 shadowTex = textureCube(map, direction);\\n#ifdef USE_VSM\\n vec2 moments = shadowTex.xy;\\n float variance = moments.y - moments.x * moments.x;\\n float mD = moments.x - dist;\\n float p = variance / (variance + mD * mD);\\n if(moments.x + 0.001 < dist){\\n return clamp(p, 0.0, 1.0);\\n }else{\\n return 1.0;\\n }\\n#else\\n return step(dist, (decodeFloat(shadowTex) + 0.0002) * range);\\n#endif\\n}\\n@end\\n@export clay.plugin.compute_shadow_map\\n#if defined(SPOT_LIGHT_SHADOWMAP_COUNT) || defined(DIRECTIONAL_LIGHT_SHADOWMAP_COUNT) || defined(POINT_LIGHT_SHADOWMAP_COUNT)\\n#ifdef SPOT_LIGHT_SHADOWMAP_COUNT\\nuniform sampler2D spotLightShadowMaps[SPOT_LIGHT_SHADOWMAP_COUNT]:unconfigurable;\\nuniform mat4 spotLightMatrices[SPOT_LIGHT_SHADOWMAP_COUNT]:unconfigurable;\\nuniform float spotLightShadowMapSizes[SPOT_LIGHT_SHADOWMAP_COUNT]:unconfigurable;\\n#endif\\n#ifdef DIRECTIONAL_LIGHT_SHADOWMAP_COUNT\\n#if defined(SHADOW_CASCADE)\\nuniform sampler2D directionalLightShadowMaps[1]:unconfigurable;\\nuniform mat4 directionalLightMatrices[SHADOW_CASCADE]:unconfigurable;\\nuniform float directionalLightShadowMapSizes[1]:unconfigurable;\\nuniform float shadowCascadeClipsNear[SHADOW_CASCADE]:unconfigurable;\\nuniform float shadowCascadeClipsFar[SHADOW_CASCADE]:unconfigurable;\\n#else\\nuniform sampler2D directionalLightShadowMaps[DIRECTIONAL_LIGHT_SHADOWMAP_COUNT]:unconfigurable;\\nuniform mat4 directionalLightMatrices[DIRECTIONAL_LIGHT_SHADOWMAP_COUNT]:unconfigurable;\\nuniform float directionalLightShadowMapSizes[DIRECTIONAL_LIGHT_SHADOWMAP_COUNT]:unconfigurable;\\n#endif\\n#endif\\n#ifdef POINT_LIGHT_SHADOWMAP_COUNT\\nuniform samplerCube pointLightShadowMaps[POINT_LIGHT_SHADOWMAP_COUNT]:unconfigurable;\\n#endif\\nuniform bool shadowEnabled : true;\\n#ifdef PCF_KERNEL_SIZE\\nuniform vec2 pcfKernel[PCF_KERNEL_SIZE];\\n#endif\\n@import clay.plugin.shadow_map_common\\n#if defined(SPOT_LIGHT_SHADOWMAP_COUNT)\\nvoid computeShadowOfSpotLights(vec3 position, inout float shadowContribs[SPOT_LIGHT_COUNT] ) {\\n float shadowContrib;\\n for(int _idx_ = 0; _idx_ < SPOT_LIGHT_SHADOWMAP_COUNT; _idx_++) {{\\n shadowContrib = computeShadowContrib(\\n spotLightShadowMaps[_idx_], spotLightMatrices[_idx_], position,\\n spotLightShadowMapSizes[_idx_]\\n );\\n shadowContribs[_idx_] = shadowContrib;\\n }}\\n for(int _idx_ = SPOT_LIGHT_SHADOWMAP_COUNT; _idx_ < SPOT_LIGHT_COUNT; _idx_++){{\\n shadowContribs[_idx_] = 1.0;\\n }}\\n}\\n#endif\\n#if defined(DIRECTIONAL_LIGHT_SHADOWMAP_COUNT)\\n#ifdef SHADOW_CASCADE\\nvoid computeShadowOfDirectionalLights(vec3 position, inout float shadowContribs[DIRECTIONAL_LIGHT_COUNT]){\\n float depth = (2.0 * gl_FragCoord.z - gl_DepthRange.near - gl_DepthRange.far)\\n / (gl_DepthRange.far - gl_DepthRange.near);\\n float shadowContrib;\\n shadowContribs[0] = 1.0;\\n for (int _idx_ = 0; _idx_ < SHADOW_CASCADE; _idx_++) {{\\n if (\\n depth >= shadowCascadeClipsNear[_idx_] &&\\n depth <= shadowCascadeClipsFar[_idx_]\\n ) {\\n shadowContrib = computeShadowContrib(\\n directionalLightShadowMaps[0], directionalLightMatrices[_idx_], position,\\n directionalLightShadowMapSizes[0],\\n vec2(1.0 / float(SHADOW_CASCADE), 1.0),\\n vec2(float(_idx_) / float(SHADOW_CASCADE), 0.0)\\n );\\n shadowContribs[0] = shadowContrib;\\n }\\n }}\\n for(int _idx_ = DIRECTIONAL_LIGHT_SHADOWMAP_COUNT; _idx_ < DIRECTIONAL_LIGHT_COUNT; _idx_++) {{\\n shadowContribs[_idx_] = 1.0;\\n }}\\n}\\n#else\\nvoid computeShadowOfDirectionalLights(vec3 position, inout float shadowContribs[DIRECTIONAL_LIGHT_COUNT]){\\n float shadowContrib;\\n for(int _idx_ = 0; _idx_ < DIRECTIONAL_LIGHT_SHADOWMAP_COUNT; _idx_++) {{\\n shadowContrib = computeShadowContrib(\\n directionalLightShadowMaps[_idx_], directionalLightMatrices[_idx_], position,\\n directionalLightShadowMapSizes[_idx_]\\n );\\n shadowContribs[_idx_] = shadowContrib;\\n }}\\n for(int _idx_ = DIRECTIONAL_LIGHT_SHADOWMAP_COUNT; _idx_ < DIRECTIONAL_LIGHT_COUNT; _idx_++) {{\\n shadowContribs[_idx_] = 1.0;\\n }}\\n}\\n#endif\\n#endif\\n#if defined(POINT_LIGHT_SHADOWMAP_COUNT)\\nvoid computeShadowOfPointLights(vec3 position, inout float shadowContribs[POINT_LIGHT_COUNT] ){\\n vec3 lightPosition;\\n vec3 direction;\\n for(int _idx_ = 0; _idx_ < POINT_LIGHT_SHADOWMAP_COUNT; _idx_++) {{\\n lightPosition = pointLightPosition[_idx_];\\n direction = position - lightPosition;\\n shadowContribs[_idx_] = computeShadowContribOmni(pointLightShadowMaps[_idx_], direction, pointLightRange[_idx_]);\\n }}\\n for(int _idx_ = POINT_LIGHT_SHADOWMAP_COUNT; _idx_ < POINT_LIGHT_COUNT; _idx_++) {{\\n shadowContribs[_idx_] = 1.0;\\n }}\\n}\\n#endif\\n#endif\\n@end\";\n","import Base from '../core/Base';\nimport glenum from '../core/glenum';\nimport Vector3 from '../math/Vector3';\nimport BoundingBox from '../math/BoundingBox';\nimport Frustum from '../math/Frustum';\nimport Matrix4 from '../math/Matrix4';\nimport Renderer from '../Renderer';\nimport Shader from '../Shader';\nimport Material from '../Material';\nimport FrameBuffer from '../FrameBuffer';\nimport Texture from '../Texture';\nimport Texture2D from '../Texture2D';\nimport TextureCube from '../TextureCube';\nimport PerspectiveCamera from '../camera/Perspective';\nimport OrthoCamera from '../camera/Orthographic';\n\nimport Pass from '../compositor/Pass';\nimport TexturePool from '../compositor/TexturePool';\n\nimport mat4 from '../glmatrix/mat4';\n\nvar targets = ['px', 'nx', 'py', 'ny', 'pz', 'nz'];\n\nimport shadowmapEssl from '../shader/source/shadowmap.glsl.js';\nShader['import'](shadowmapEssl);\n\nfunction getDepthMaterialUniform(renderable, depthMaterial, symbol) {\n if (symbol === 'alphaMap') {\n return renderable.material.get('diffuseMap');\n }\n else if (symbol === 'alphaCutoff') {\n if (renderable.material.isDefined('fragment', 'ALPHA_TEST')\n && renderable.material.get('diffuseMap')\n ) {\n var alphaCutoff = renderable.material.get('alphaCutoff');\n return alphaCutoff || 0;\n }\n return 0;\n }\n else if (symbol === 'uvRepeat') {\n return renderable.material.get('uvRepeat');\n }\n else if (symbol === 'uvOffset') {\n return renderable.material.get('uvOffset');\n }\n else {\n return depthMaterial.get(symbol);\n }\n}\n\nfunction isDepthMaterialChanged(renderable, prevRenderable) {\n var matA = renderable.material;\n var matB = prevRenderable.material;\n return matA.get('diffuseMap') !== matB.get('diffuseMap')\n || (matA.get('alphaCutoff') || 0) !== (matB.get('alphaCutoff') || 0);\n}\n\n/**\n * Pass rendering shadow map.\n *\n * @constructor clay.prePass.ShadowMap\n * @extends clay.core.Base\n * @example\n * var shadowMapPass = new clay.prePass.ShadowMap({\n * softShadow: clay.prePass.ShadowMap.VSM\n * });\n * ...\n * animation.on('frame', function (frameTime) {\n * shadowMapPass.render(renderer, scene, camera);\n * renderer.render(scene, camera);\n * });\n */\nvar ShadowMapPass = Base.extend(function () {\n return /** @lends clay.prePass.ShadowMap# */ {\n /**\n * Soft shadow technique.\n * Can be {@link clay.prePass.ShadowMap.PCF} or {@link clay.prePass.ShadowMap.VSM}\n * @type {number}\n */\n softShadow: ShadowMapPass.PCF,\n\n /**\n * Soft shadow blur size\n * @type {number}\n */\n shadowBlur: 1.0,\n\n lightFrustumBias: 'auto',\n\n kernelPCF: new Float32Array([\n 1, 0,\n 1, 1,\n -1, 1,\n 0, 1,\n -1, 0,\n -1, -1,\n 1, -1,\n 0, -1\n ]),\n\n precision: 'highp',\n\n _lastRenderNotCastShadow: false,\n\n _frameBuffer: new FrameBuffer(),\n\n _textures: {},\n _shadowMapNumber: {\n 'POINT_LIGHT': 0,\n 'DIRECTIONAL_LIGHT': 0,\n 'SPOT_LIGHT': 0\n },\n\n _depthMaterials: {},\n _distanceMaterials: {},\n\n _receivers: [],\n _lightsCastShadow: [],\n\n _lightCameras: {},\n _lightMaterials: {},\n\n _texturePool: new TexturePool()\n };\n}, function () {\n // Gaussian filter pass for VSM\n this._gaussianPassH = new Pass({\n fragment: Shader.source('clay.compositor.gaussian_blur')\n });\n this._gaussianPassV = new Pass({\n fragment: Shader.source('clay.compositor.gaussian_blur')\n });\n this._gaussianPassH.setUniform('blurSize', this.shadowBlur);\n this._gaussianPassH.setUniform('blurDir', 0.0);\n this._gaussianPassV.setUniform('blurSize', this.shadowBlur);\n this._gaussianPassV.setUniform('blurDir', 1.0);\n\n this._outputDepthPass = new Pass({\n fragment: Shader.source('clay.sm.debug_depth')\n });\n}, {\n /**\n * Render scene to shadow textures\n * @param {clay.Renderer} renderer\n * @param {clay.Scene} scene\n * @param {clay.Camera} sceneCamera\n * @param {boolean} [notUpdateScene=false]\n * @memberOf clay.prePass.ShadowMap.prototype\n */\n render: function (renderer, scene, sceneCamera, notUpdateScene) {\n if (!sceneCamera) {\n sceneCamera = scene.getMainCamera();\n }\n this.trigger('beforerender', this, renderer, scene, sceneCamera);\n this._renderShadowPass(renderer, scene, sceneCamera, notUpdateScene);\n this.trigger('afterrender', this, renderer, scene, sceneCamera);\n },\n\n /**\n * Debug rendering of shadow textures\n * @param {clay.Renderer} renderer\n * @param {number} size\n * @memberOf clay.prePass.ShadowMap.prototype\n */\n renderDebug: function (renderer, size) {\n renderer.saveClear();\n var viewport = renderer.viewport;\n var x = 0, y = 0;\n var width = size || viewport.width / 4;\n var height = width;\n if (this.softShadow === ShadowMapPass.VSM) {\n this._outputDepthPass.material.define('fragment', 'USE_VSM');\n }\n else {\n this._outputDepthPass.material.undefine('fragment', 'USE_VSM');\n }\n for (var name in this._textures) {\n var texture = this._textures[name];\n renderer.setViewport(x, y, width * texture.width / texture.height, height);\n this._outputDepthPass.setUniform('depthMap', texture);\n this._outputDepthPass.render(renderer);\n x += width * texture.width / texture.height;\n }\n renderer.setViewport(viewport);\n renderer.restoreClear();\n },\n\n _updateReceivers: function (renderer, mesh) {\n if (mesh.receiveShadow) {\n this._receivers.push(mesh);\n mesh.material.set('shadowEnabled', 1);\n\n mesh.material.set('pcfKernel', this.kernelPCF);\n }\n else {\n mesh.material.set('shadowEnabled', 0);\n }\n\n if (this.softShadow === ShadowMapPass.VSM) {\n mesh.material.define('fragment', 'USE_VSM');\n mesh.material.undefine('fragment', 'PCF_KERNEL_SIZE');\n }\n else {\n mesh.material.undefine('fragment', 'USE_VSM');\n var kernelPCF = this.kernelPCF;\n if (kernelPCF && kernelPCF.length) {\n mesh.material.define('fragment', 'PCF_KERNEL_SIZE', kernelPCF.length / 2);\n }\n else {\n mesh.material.undefine('fragment', 'PCF_KERNEL_SIZE');\n }\n }\n },\n\n _update: function (renderer, scene) {\n var self = this;\n scene.traverse(function (renderable) {\n if (renderable.isRenderable()) {\n self._updateReceivers(renderer, renderable);\n }\n });\n\n for (var i = 0; i < scene.lights.length; i++) {\n var light = scene.lights[i];\n if (light.castShadow && !light.invisible) {\n this._lightsCastShadow.push(light);\n }\n }\n },\n\n _renderShadowPass: function (renderer, scene, sceneCamera, notUpdateScene) {\n // reset\n for (var name in this._shadowMapNumber) {\n this._shadowMapNumber[name] = 0;\n }\n this._lightsCastShadow.length = 0;\n this._receivers.length = 0;\n\n var _gl = renderer.gl;\n\n if (!notUpdateScene) {\n scene.update();\n }\n if (sceneCamera) {\n sceneCamera.update();\n }\n\n scene.updateLights();\n this._update(renderer, scene);\n\n // Needs to update the receivers again if shadows come from 1 to 0.\n if (!this._lightsCastShadow.length && this._lastRenderNotCastShadow) {\n return;\n }\n\n this._lastRenderNotCastShadow = this._lightsCastShadow === 0;\n\n _gl.enable(_gl.DEPTH_TEST);\n _gl.depthMask(true);\n _gl.disable(_gl.BLEND);\n\n // Clear with high-z, so the part not rendered will not been shadowed\n // TODO\n // TODO restore\n _gl.clearColor(1.0, 1.0, 1.0, 1.0);\n\n // Shadow uniforms\n var spotLightShadowMaps = [];\n var spotLightMatrices = [];\n var directionalLightShadowMaps = [];\n var directionalLightMatrices = [];\n var shadowCascadeClips = [];\n var pointLightShadowMaps = [];\n\n var dirLightHasCascade;\n // Create textures for shadow map\n for (var i = 0; i < this._lightsCastShadow.length; i++) {\n var light = this._lightsCastShadow[i];\n if (light.type === 'DIRECTIONAL_LIGHT') {\n\n if (dirLightHasCascade) {\n console.warn('Only one direectional light supported with shadow cascade');\n continue;\n }\n if (light.shadowCascade > 4) {\n console.warn('Support at most 4 cascade');\n continue;\n }\n if (light.shadowCascade > 1) {\n dirLightHasCascade = light;\n }\n\n this.renderDirectionalLightShadow(\n renderer,\n scene,\n sceneCamera,\n light,\n shadowCascadeClips,\n directionalLightMatrices,\n directionalLightShadowMaps\n );\n }\n else if (light.type === 'SPOT_LIGHT') {\n this.renderSpotLightShadow(\n renderer,\n scene,\n light,\n spotLightMatrices,\n spotLightShadowMaps\n );\n }\n else if (light.type === 'POINT_LIGHT') {\n this.renderPointLightShadow(\n renderer,\n scene,\n light,\n pointLightShadowMaps\n );\n }\n\n this._shadowMapNumber[light.type]++;\n }\n\n for (var lightType in this._shadowMapNumber) {\n var number = this._shadowMapNumber[lightType];\n var key = lightType + '_SHADOWMAP_COUNT';\n for (var i = 0; i < this._receivers.length; i++) {\n var mesh = this._receivers[i];\n var material = mesh.material;\n if (material.fragmentDefines[key] !== number) {\n if (number > 0) {\n material.define('fragment', key, number);\n }\n else if (material.isDefined('fragment', key)) {\n material.undefine('fragment', key);\n }\n }\n }\n }\n for (var i = 0; i < this._receivers.length; i++) {\n var mesh = this._receivers[i];\n var material = mesh.material;\n if (dirLightHasCascade) {\n material.define('fragment', 'SHADOW_CASCADE', dirLightHasCascade.shadowCascade);\n }\n else {\n material.undefine('fragment', 'SHADOW_CASCADE');\n }\n }\n\n var shadowUniforms = scene.shadowUniforms;\n\n function getSize(texture) {\n return texture.height;\n }\n if (directionalLightShadowMaps.length > 0) {\n var directionalLightShadowMapSizes = directionalLightShadowMaps.map(getSize);\n shadowUniforms.directionalLightShadowMaps = { value: directionalLightShadowMaps, type: 'tv' };\n shadowUniforms.directionalLightMatrices = { value: directionalLightMatrices, type: 'm4v' };\n shadowUniforms.directionalLightShadowMapSizes = { value: directionalLightShadowMapSizes, type: '1fv' };\n if (dirLightHasCascade) {\n var shadowCascadeClipsNear = shadowCascadeClips.slice();\n var shadowCascadeClipsFar = shadowCascadeClips.slice();\n shadowCascadeClipsNear.pop();\n shadowCascadeClipsFar.shift();\n\n // Iterate from far to near\n shadowCascadeClipsNear.reverse();\n shadowCascadeClipsFar.reverse();\n // directionalLightShadowMaps.reverse();\n directionalLightMatrices.reverse();\n shadowUniforms.shadowCascadeClipsNear = { value: shadowCascadeClipsNear, type: '1fv' };\n shadowUniforms.shadowCascadeClipsFar = { value: shadowCascadeClipsFar, type: '1fv' };\n }\n }\n\n if (spotLightShadowMaps.length > 0) {\n var spotLightShadowMapSizes = spotLightShadowMaps.map(getSize);\n var shadowUniforms = scene.shadowUniforms;\n shadowUniforms.spotLightShadowMaps = { value: spotLightShadowMaps, type: 'tv' };\n shadowUniforms.spotLightMatrices = { value: spotLightMatrices, type: 'm4v' };\n shadowUniforms.spotLightShadowMapSizes = { value: spotLightShadowMapSizes, type: '1fv' };\n }\n\n if (pointLightShadowMaps.length > 0) {\n shadowUniforms.pointLightShadowMaps = { value: pointLightShadowMaps, type: 'tv' };\n }\n },\n\n renderDirectionalLightShadow: (function () {\n\n var splitFrustum = new Frustum();\n var splitProjMatrix = new Matrix4();\n var cropBBox = new BoundingBox();\n var cropMatrix = new Matrix4();\n var lightViewMatrix = new Matrix4();\n var lightViewProjMatrix = new Matrix4();\n var lightProjMatrix = new Matrix4();\n\n return function (renderer, scene, sceneCamera, light, shadowCascadeClips, directionalLightMatrices, directionalLightShadowMaps) {\n\n var defaultShadowMaterial = this._getDepthMaterial(light);\n var passConfig = {\n getMaterial: function (renderable) {\n return renderable.shadowDepthMaterial || defaultShadowMaterial;\n },\n isMaterialChanged: isDepthMaterialChanged,\n getUniform: getDepthMaterialUniform,\n ifRender: function (renderable) {\n return renderable.castShadow;\n },\n sortCompare: Renderer.opaqueSortCompare\n };\n\n // First frame\n if (!scene.viewBoundingBoxLastFrame.isFinite()) {\n var boundingBox = scene.getBoundingBox();\n scene.viewBoundingBoxLastFrame\n .copy(boundingBox).applyTransform(sceneCamera.viewMatrix);\n }\n // Considering moving speed since the bounding box is from last frame\n // TODO: add a bias\n var clippedFar = Math.min(-scene.viewBoundingBoxLastFrame.min.z, sceneCamera.far);\n var clippedNear = Math.max(-scene.viewBoundingBoxLastFrame.max.z, sceneCamera.near);\n\n var lightCamera = this._getDirectionalLightCamera(light, scene, sceneCamera);\n\n var lvpMat4Arr = lightViewProjMatrix.array;\n lightProjMatrix.copy(lightCamera.projectionMatrix);\n mat4.invert(lightViewMatrix.array, lightCamera.worldTransform.array);\n mat4.multiply(lightViewMatrix.array, lightViewMatrix.array, sceneCamera.worldTransform.array);\n mat4.multiply(lvpMat4Arr, lightProjMatrix.array, lightViewMatrix.array);\n\n var clipPlanes = [];\n var isPerspective = sceneCamera instanceof PerspectiveCamera;\n\n var scaleZ = (sceneCamera.near + sceneCamera.far) / (sceneCamera.near - sceneCamera.far);\n var offsetZ = 2 * sceneCamera.near * sceneCamera.far / (sceneCamera.near - sceneCamera.far);\n for (var i = 0; i <= light.shadowCascade; i++) {\n var clog = clippedNear * Math.pow(clippedFar / clippedNear, i / light.shadowCascade);\n var cuni = clippedNear + (clippedFar - clippedNear) * i / light.shadowCascade;\n var c = clog * light.cascadeSplitLogFactor + cuni * (1 - light.cascadeSplitLogFactor);\n clipPlanes.push(c);\n shadowCascadeClips.push(-(-c * scaleZ + offsetZ) / -c);\n }\n var texture = this._getTexture(light, light.shadowCascade);\n directionalLightShadowMaps.push(texture);\n\n var viewport = renderer.viewport;\n\n var _gl = renderer.gl;\n this._frameBuffer.attach(texture);\n this._frameBuffer.bind(renderer);\n _gl.clear(_gl.COLOR_BUFFER_BIT | _gl.DEPTH_BUFFER_BIT);\n\n for (var i = 0; i < light.shadowCascade; i++) {\n // Get the splitted frustum\n var nearPlane = clipPlanes[i];\n var farPlane = clipPlanes[i + 1];\n if (isPerspective) {\n mat4.perspective(splitProjMatrix.array, sceneCamera.fov / 180 * Math.PI, sceneCamera.aspect, nearPlane, farPlane);\n }\n else {\n mat4.ortho(\n splitProjMatrix.array,\n sceneCamera.left, sceneCamera.right, sceneCamera.bottom, sceneCamera.top,\n nearPlane, farPlane\n );\n }\n splitFrustum.setFromProjection(splitProjMatrix);\n splitFrustum.getTransformedBoundingBox(cropBBox, lightViewMatrix);\n cropBBox.applyProjection(lightProjMatrix);\n var _min = cropBBox.min.array;\n var _max = cropBBox.max.array;\n _min[0] = Math.max(_min[0], -1);\n _min[1] = Math.max(_min[1], -1);\n _max[0] = Math.min(_max[0], 1);\n _max[1] = Math.min(_max[1], 1);\n cropMatrix.ortho(_min[0], _max[0], _min[1], _max[1], 1, -1);\n lightCamera.projectionMatrix.multiplyLeft(cropMatrix);\n\n var shadowSize = light.shadowResolution || 512;\n\n // Reversed, left to right => far to near\n renderer.setViewport((light.shadowCascade - i - 1) * shadowSize, 0, shadowSize, shadowSize, 1);\n\n var renderList = scene.updateRenderList(lightCamera);\n renderer.renderPass(renderList.opaque, lightCamera, passConfig);\n\n // Filter for VSM\n if (this.softShadow === ShadowMapPass.VSM) {\n this._gaussianFilter(renderer, texture, texture.width);\n }\n\n var matrix = new Matrix4();\n matrix.copy(lightCamera.viewMatrix)\n .multiplyLeft(lightCamera.projectionMatrix);\n\n directionalLightMatrices.push(matrix.array);\n\n lightCamera.projectionMatrix.copy(lightProjMatrix);\n }\n\n this._frameBuffer.unbind(renderer);\n\n renderer.setViewport(viewport);\n };\n })(),\n\n renderSpotLightShadow: function (renderer, scene, light, spotLightMatrices, spotLightShadowMaps) {\n\n var texture = this._getTexture(light);\n var lightCamera = this._getSpotLightCamera(light);\n var _gl = renderer.gl;\n\n this._frameBuffer.attach(texture);\n this._frameBuffer.bind(renderer);\n\n _gl.clear(_gl.COLOR_BUFFER_BIT | _gl.DEPTH_BUFFER_BIT);\n\n var defaultShadowMaterial = this._getDepthMaterial(light);\n var passConfig = {\n getMaterial: function (renderable) {\n return renderable.shadowDepthMaterial || defaultShadowMaterial;\n },\n isMaterialChanged: isDepthMaterialChanged,\n getUniform: getDepthMaterialUniform,\n ifRender: function (renderable) {\n return renderable.castShadow;\n },\n sortCompare: Renderer.opaqueSortCompare\n };\n\n var renderList = scene.updateRenderList(lightCamera);\n renderer.renderPass(renderList.opaque, lightCamera, passConfig);\n\n this._frameBuffer.unbind(renderer);\n\n // Filter for VSM\n if (this.softShadow === ShadowMapPass.VSM) {\n this._gaussianFilter(renderer, texture, texture.width);\n }\n\n var matrix = new Matrix4();\n matrix.copy(lightCamera.worldTransform)\n .invert()\n .multiplyLeft(lightCamera.projectionMatrix);\n\n spotLightShadowMaps.push(texture);\n spotLightMatrices.push(matrix.array);\n },\n\n renderPointLightShadow: function (renderer, scene, light, pointLightShadowMaps) {\n var texture = this._getTexture(light);\n var _gl = renderer.gl;\n pointLightShadowMaps.push(texture);\n\n var defaultShadowMaterial = this._getDepthMaterial(light);\n var passConfig = {\n getMaterial: function (renderable) {\n return renderable.shadowDepthMaterial || defaultShadowMaterial;\n },\n getUniform: getDepthMaterialUniform,\n sortCompare: Renderer.opaqueSortCompare\n };\n\n var renderListEachSide = {\n px: [], py: [], pz: [], nx: [], ny: [], nz: []\n };\n var bbox = new BoundingBox();\n var lightWorldPosition = light.getWorldPosition().array;\n var lightBBox = new BoundingBox();\n var range = light.range;\n lightBBox.min.setArray(lightWorldPosition);\n lightBBox.max.setArray(lightWorldPosition);\n var extent = new Vector3(range, range, range);\n lightBBox.max.add(extent);\n lightBBox.min.sub(extent);\n\n var targetsNeedRender = { px: false, py: false, pz: false, nx: false, ny: false, nz: false };\n scene.traverse(function (renderable) {\n if (renderable.isRenderable() && renderable.castShadow) {\n var geometry = renderable.geometry;\n if (!geometry.boundingBox) {\n for (var i = 0; i < targets.length; i++) {\n renderListEachSide[targets[i]].push(renderable);\n }\n return;\n }\n bbox.transformFrom(geometry.boundingBox, renderable.worldTransform);\n if (!bbox.intersectBoundingBox(lightBBox)) {\n return;\n }\n\n bbox.updateVertices();\n for (var i = 0; i < targets.length; i++) {\n targetsNeedRender[targets[i]] = false;\n }\n for (var i = 0; i < 8; i++) {\n var vtx = bbox.vertices[i];\n var x = vtx[0] - lightWorldPosition[0];\n var y = vtx[1] - lightWorldPosition[1];\n var z = vtx[2] - lightWorldPosition[2];\n var absx = Math.abs(x);\n var absy = Math.abs(y);\n var absz = Math.abs(z);\n if (absx > absy) {\n if (absx > absz) {\n targetsNeedRender[x > 0 ? 'px' : 'nx'] = true;\n }\n else {\n targetsNeedRender[z > 0 ? 'pz' : 'nz'] = true;\n }\n }\n else {\n if (absy > absz) {\n targetsNeedRender[y > 0 ? 'py' : 'ny'] = true;\n }\n else {\n targetsNeedRender[z > 0 ? 'pz' : 'nz'] = true;\n }\n }\n }\n for (var i = 0; i < targets.length; i++) {\n if (targetsNeedRender[targets[i]]) {\n renderListEachSide[targets[i]].push(renderable);\n }\n }\n }\n });\n\n for (var i = 0; i < 6; i++) {\n var target = targets[i];\n var camera = this._getPointLightCamera(light, target);\n\n this._frameBuffer.attach(texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i);\n this._frameBuffer.bind(renderer);\n _gl.clear(_gl.COLOR_BUFFER_BIT | _gl.DEPTH_BUFFER_BIT);\n\n renderer.renderPass(renderListEachSide[target], camera, passConfig);\n }\n\n this._frameBuffer.unbind(renderer);\n },\n\n _getDepthMaterial: function (light) {\n var shadowMaterial = this._lightMaterials[light.__uid__];\n var isPointLight = light.type === 'POINT_LIGHT';\n if (!shadowMaterial) {\n var shaderPrefix = isPointLight ? 'clay.sm.distance.' : 'clay.sm.depth.';\n shadowMaterial = new Material({\n precision: this.precision,\n shader: new Shader(Shader.source(shaderPrefix + 'vertex'), Shader.source(shaderPrefix + 'fragment'))\n });\n\n this._lightMaterials[light.__uid__] = shadowMaterial;\n }\n if (light.shadowSlopeScale != null) {\n shadowMaterial.setUniform('slopeScale', light.shadowSlopeScale);\n }\n if (light.shadowBias != null) {\n shadowMaterial.setUniform('bias', light.shadowBias);\n }\n if (this.softShadow === ShadowMapPass.VSM) {\n shadowMaterial.define('fragment', 'USE_VSM');\n }\n else {\n shadowMaterial.undefine('fragment', 'USE_VSM');\n }\n\n if (isPointLight) {\n shadowMaterial.set('lightPosition', light.getWorldPosition().array);\n shadowMaterial.set('range', light.range);\n }\n\n return shadowMaterial;\n },\n\n _gaussianFilter: function (renderer, texture, size) {\n var parameter = {\n width: size,\n height: size,\n type: Texture.FLOAT\n };\n var tmpTexture = this._texturePool.get(parameter);\n\n this._frameBuffer.attach(tmpTexture);\n this._frameBuffer.bind(renderer);\n this._gaussianPassH.setUniform('texture', texture);\n this._gaussianPassH.setUniform('textureWidth', size);\n this._gaussianPassH.render(renderer);\n\n this._frameBuffer.attach(texture);\n this._gaussianPassV.setUniform('texture', tmpTexture);\n this._gaussianPassV.setUniform('textureHeight', size);\n this._gaussianPassV.render(renderer);\n this._frameBuffer.unbind(renderer);\n\n this._texturePool.put(tmpTexture);\n },\n\n _getTexture: function (light, cascade) {\n var key = light.__uid__;\n var texture = this._textures[key];\n var resolution = light.shadowResolution || 512;\n cascade = cascade || 1;\n if (!texture) {\n if (light.type === 'POINT_LIGHT') {\n texture = new TextureCube();\n }\n else {\n texture = new Texture2D();\n }\n // At most 4 cascade\n // TODO share with height ?\n texture.width = resolution * cascade;\n texture.height = resolution;\n if (this.softShadow === ShadowMapPass.VSM) {\n texture.type = Texture.FLOAT;\n texture.anisotropic = 4;\n }\n else {\n texture.minFilter = glenum.NEAREST;\n texture.magFilter = glenum.NEAREST;\n texture.useMipmap = false;\n }\n this._textures[key] = texture;\n }\n\n return texture;\n },\n\n _getPointLightCamera: function (light, target) {\n if (!this._lightCameras.point) {\n this._lightCameras.point = {\n px: new PerspectiveCamera(),\n nx: new PerspectiveCamera(),\n py: new PerspectiveCamera(),\n ny: new PerspectiveCamera(),\n pz: new PerspectiveCamera(),\n nz: new PerspectiveCamera()\n };\n }\n var camera = this._lightCameras.point[target];\n\n camera.far = light.range;\n camera.fov = 90;\n camera.position.set(0, 0, 0);\n switch (target) {\n case 'px':\n camera.lookAt(Vector3.POSITIVE_X, Vector3.NEGATIVE_Y);\n break;\n case 'nx':\n camera.lookAt(Vector3.NEGATIVE_X, Vector3.NEGATIVE_Y);\n break;\n case 'py':\n camera.lookAt(Vector3.POSITIVE_Y, Vector3.POSITIVE_Z);\n break;\n case 'ny':\n camera.lookAt(Vector3.NEGATIVE_Y, Vector3.NEGATIVE_Z);\n break;\n case 'pz':\n camera.lookAt(Vector3.POSITIVE_Z, Vector3.NEGATIVE_Y);\n break;\n case 'nz':\n camera.lookAt(Vector3.NEGATIVE_Z, Vector3.NEGATIVE_Y);\n break;\n }\n light.getWorldPosition(camera.position);\n camera.update();\n\n return camera;\n },\n\n _getDirectionalLightCamera: (function () {\n var lightViewMatrix = new Matrix4();\n var sceneViewBoundingBox = new BoundingBox();\n var lightViewBBox = new BoundingBox();\n // Camera of directional light will be adjusted\n // to contain the view frustum and scene bounding box as tightly as possible\n return function (light, scene, sceneCamera) {\n if (!this._lightCameras.directional) {\n this._lightCameras.directional = new OrthoCamera();\n }\n var camera = this._lightCameras.directional;\n\n sceneViewBoundingBox.copy(scene.viewBoundingBoxLastFrame);\n sceneViewBoundingBox.intersection(sceneCamera.frustum.boundingBox);\n // Move to the center of frustum(in world space)\n camera.position\n .copy(sceneViewBoundingBox.min)\n .add(sceneViewBoundingBox.max)\n .scale(0.5)\n .transformMat4(sceneCamera.worldTransform);\n camera.rotation.copy(light.rotation);\n camera.scale.copy(light.scale);\n camera.updateWorldTransform();\n\n // Transform to light view space\n Matrix4.invert(lightViewMatrix, camera.worldTransform);\n Matrix4.multiply(lightViewMatrix, lightViewMatrix, sceneCamera.worldTransform);\n\n lightViewBBox.copy(sceneViewBoundingBox).applyTransform(lightViewMatrix);\n\n var min = lightViewBBox.min.array;\n var max = lightViewBBox.max.array;\n\n // Move camera to adjust the near to 0\n camera.position.set((min[0] + max[0]) / 2, (min[1] + max[1]) / 2, max[2])\n .transformMat4(camera.worldTransform);\n camera.near = 0;\n camera.far = -min[2] + max[2];\n // Make sure receivers not in the frustum will stil receive the shadow.\n if (isNaN(this.lightFrustumBias)) {\n camera.far *= 4;\n }\n else {\n camera.far += this.lightFrustumBias;\n }\n camera.left = min[0];\n camera.right = max[0];\n camera.top = max[1];\n camera.bottom = min[1];\n camera.update(true);\n\n return camera;\n };\n })(),\n\n _getSpotLightCamera: function (light) {\n if (!this._lightCameras.spot) {\n this._lightCameras.spot = new PerspectiveCamera();\n }\n var camera = this._lightCameras.spot;\n // Update properties\n camera.fov = light.penumbraAngle * 2;\n camera.far = light.range;\n camera.worldTransform.copy(light.worldTransform);\n camera.updateProjectionMatrix();\n mat4.invert(camera.viewMatrix.array, camera.worldTransform.array);\n\n return camera;\n },\n\n /**\n * @param {clay.Renderer|WebGLRenderingContext} [renderer]\n * @memberOf clay.prePass.ShadowMap.prototype\n */\n // PENDING Renderer or WebGLRenderingContext\n dispose: function (renderer) {\n var _gl = renderer.gl || renderer;\n\n if (this._frameBuffer) {\n this._frameBuffer.dispose(_gl);\n }\n\n for (var name in this._textures) {\n this._textures[name].dispose(_gl);\n }\n\n this._texturePool.clear(renderer.gl);\n\n this._depthMaterials = {};\n this._distanceMaterials = {};\n this._textures = {};\n this._lightCameras = {};\n this._shadowMapNumber = {\n 'POINT_LIGHT': 0,\n 'DIRECTIONAL_LIGHT': 0,\n 'SPOT_LIGHT': 0\n };\n this._meshMaterials = {};\n\n for (var i = 0; i < this._receivers.length; i++) {\n var mesh = this._receivers[i];\n // Mesh may be disposed\n if (mesh.material) {\n var material = mesh.material;\n material.undefine('fragment', 'POINT_LIGHT_SHADOW_COUNT');\n material.undefine('fragment', 'DIRECTIONAL_LIGHT_SHADOW_COUNT');\n material.undefine('fragment', 'AMBIENT_LIGHT_SHADOW_COUNT');\n material.set('shadowEnabled', 0);\n }\n }\n\n this._receivers = [];\n this._lightsCastShadow = [];\n }\n});\n\n/**\n * @name clay.prePass.ShadowMap.VSM\n * @type {number}\n */\nShadowMapPass.VSM = 1;\n\n/**\n * @name clay.prePass.ShadowMap.PCF\n * @type {number}\n */\nShadowMapPass.PCF = 2;\n\nexport default ShadowMapPass;\n","import Base from '../core/Base';\n\n// PENDING\n// Use topological sort ?\n\n/**\n * Node of graph based post processing.\n *\n * @constructor clay.compositor.CompositorNode\n * @extends clay.core.Base\n *\n */\nvar CompositorNode = Base.extend(function () {\n return /** @lends clay.compositor.CompositorNode# */ {\n /**\n * @type {string}\n */\n name: '',\n\n /**\n * Input links, will be updated by the graph\n * @example:\n * inputName: {\n * node: someNode,\n * pin: 'xxxx'\n * }\n * @type {Object}\n */\n inputLinks: {},\n\n /**\n * Output links, will be updated by the graph\n * @example:\n * outputName: {\n * node: someNode,\n * pin: 'xxxx'\n * }\n * @type {Object}\n */\n outputLinks: {},\n\n // Save the output texture of previous frame\n // Will be used when there exist a circular reference\n _prevOutputTextures: {},\n _outputTextures: {},\n\n // Example: { name: 2 }\n _outputReferences: {},\n\n _rendering: false,\n // If rendered in this frame\n _rendered: false,\n\n _compositor: null\n };\n},\n/** @lends clay.compositor.CompositorNode.prototype */\n{\n\n // TODO Remove parameter function callback\n updateParameter: function (outputName, renderer) {\n var outputInfo = this.outputs[outputName];\n var parameters = outputInfo.parameters;\n var parametersCopy = outputInfo._parametersCopy;\n if (!parametersCopy) {\n parametersCopy = outputInfo._parametersCopy = {};\n }\n if (parameters) {\n for (var key in parameters) {\n if (key !== 'width' && key !== 'height') {\n parametersCopy[key] = parameters[key];\n }\n }\n }\n var width, height;\n if (parameters.width instanceof Function) {\n width = parameters.width.call(this, renderer);\n }\n else {\n width = parameters.width;\n }\n if (parameters.height instanceof Function) {\n height = parameters.height.call(this, renderer);\n }\n else {\n height = parameters.height;\n }\n if (\n parametersCopy.width !== width\n || parametersCopy.height !== height\n ) {\n if (this._outputTextures[outputName]) {\n this._outputTextures[outputName].dispose(renderer.gl);\n }\n }\n parametersCopy.width = width;\n parametersCopy.height = height;\n\n return parametersCopy;\n },\n\n /**\n * Set parameter\n * @param {string} name\n * @param {} value\n */\n setParameter: function (name, value) {},\n /**\n * Get parameter value\n * @param {string} name\n * @return {}\n */\n getParameter: function (name) {},\n /**\n * Set parameters\n * @param {Object} obj\n */\n setParameters: function (obj) {\n for (var name in obj) {\n this.setParameter(name, obj[name]);\n }\n },\n\n render: function () {},\n\n getOutput: function (renderer /*optional*/, name) {\n if (name == null) {\n // Return the output texture without rendering\n name = renderer;\n return this._outputTextures[name];\n }\n var outputInfo = this.outputs[name];\n if (!outputInfo) {\n return ;\n }\n\n // Already been rendered in this frame\n if (this._rendered) {\n // Force return texture in last frame\n if (outputInfo.outputLastFrame) {\n return this._prevOutputTextures[name];\n }\n else {\n return this._outputTextures[name];\n }\n }\n else if (\n // TODO\n this._rendering // Solve Circular Reference\n ) {\n if (!this._prevOutputTextures[name]) {\n // Create a blank texture at first pass\n this._prevOutputTextures[name] = this._compositor.allocateTexture(outputInfo.parameters || {});\n }\n return this._prevOutputTextures[name];\n }\n\n this.render(renderer);\n\n return this._outputTextures[name];\n },\n\n removeReference: function (outputName) {\n this._outputReferences[outputName]--;\n if (this._outputReferences[outputName] === 0) {\n var outputInfo = this.outputs[outputName];\n if (outputInfo.keepLastFrame) {\n if (this._prevOutputTextures[outputName]) {\n this._compositor.releaseTexture(this._prevOutputTextures[outputName]);\n }\n this._prevOutputTextures[outputName] = this._outputTextures[outputName];\n }\n else {\n // Output of this node have alreay been used by all other nodes\n // Put the texture back to the pool.\n this._compositor.releaseTexture(this._outputTextures[outputName]);\n }\n }\n },\n\n link: function (inputPinName, fromNode, fromPinName) {\n\n // The relationship from output pin to input pin is one-on-multiple\n this.inputLinks[inputPinName] = {\n node: fromNode,\n pin: fromPinName\n };\n if (!fromNode.outputLinks[fromPinName]) {\n fromNode.outputLinks[fromPinName] = [];\n }\n fromNode.outputLinks[fromPinName].push({\n node: this,\n pin: inputPinName\n });\n\n // Enabled the pin texture in shader\n this.pass.material.enableTexture(inputPinName);\n },\n\n clear: function () {\n this.inputLinks = {};\n this.outputLinks = {};\n },\n\n updateReference: function (outputName) {\n if (!this._rendering) {\n this._rendering = true;\n for (var inputName in this.inputLinks) {\n var link = this.inputLinks[inputName];\n link.node.updateReference(link.pin);\n }\n this._rendering = false;\n }\n if (outputName) {\n this._outputReferences[outputName] ++;\n }\n },\n\n beforeFrame: function () {\n this._rendered = false;\n\n for (var name in this.outputLinks) {\n this._outputReferences[name] = 0;\n }\n },\n\n afterFrame: function () {\n // Put back all the textures to pool\n for (var name in this.outputLinks) {\n if (this._outputReferences[name] > 0) {\n var outputInfo = this.outputs[name];\n if (outputInfo.keepLastFrame) {\n if (this._prevOutputTextures[name]) {\n this._compositor.releaseTexture(this._prevOutputTextures[name]);\n }\n this._prevOutputTextures[name] = this._outputTextures[name];\n }\n else {\n this._compositor.releaseTexture(this._outputTextures[name]);\n }\n }\n }\n }\n});\n\nexport default CompositorNode;\n","import Base from '../core/Base';\nimport GraphNode from './CompositorNode';\n\n/**\n * @constructor clay.compositor.Graph\n * @extends clay.core.Base\n */\nvar Graph = Base.extend(function () {\n return /** @lends clay.compositor.Graph# */ {\n /**\n * @type {Array.}\n */\n nodes: []\n };\n},\n/** @lends clay.compositor.Graph.prototype */\n{\n\n /**\n * Mark to update\n */\n dirty: function () {\n this._dirty = true;\n },\n /**\n * @param {clay.compositor.CompositorNode} node\n */\n addNode: function (node) {\n\n if (this.nodes.indexOf(node) >= 0) {\n return;\n }\n\n this.nodes.push(node);\n\n this._dirty = true;\n },\n /**\n * @param {clay.compositor.CompositorNode|string} node\n */\n removeNode: function (node) {\n if (typeof node === 'string') {\n node = this.getNodeByName(node);\n }\n var idx = this.nodes.indexOf(node);\n if (idx >= 0) {\n this.nodes.splice(idx, 1);\n this._dirty = true;\n }\n },\n /**\n * @param {string} name\n * @return {clay.compositor.CompositorNode}\n */\n getNodeByName: function (name) {\n for (var i = 0; i < this.nodes.length; i++) {\n if (this.nodes[i].name === name) {\n return this.nodes[i];\n }\n }\n },\n /**\n * Update links of graph\n */\n update: function () {\n for (var i = 0; i < this.nodes.length; i++) {\n this.nodes[i].clear();\n }\n // Traverse all the nodes and build the graph\n for (var i = 0; i < this.nodes.length; i++) {\n var node = this.nodes[i];\n\n if (!node.inputs) {\n continue;\n }\n for (var inputName in node.inputs) {\n if (!node.inputs[inputName]) {\n continue;\n }\n if (node.pass && !node.pass.material.isUniformEnabled(inputName)) {\n console.warn('Pin ' + node.name + '.' + inputName + ' not used.');\n continue;\n }\n var fromPinInfo = node.inputs[inputName];\n\n var fromPin = this.findPin(fromPinInfo);\n if (fromPin) {\n node.link(inputName, fromPin.node, fromPin.pin);\n }\n else {\n if (typeof fromPinInfo === 'string') {\n console.warn('Node ' + fromPinInfo + ' not exist');\n }\n else {\n console.warn('Pin of ' + fromPinInfo.node + '.' + fromPinInfo.pin + ' not exist');\n }\n }\n }\n }\n },\n\n findPin: function (input) {\n var node;\n // Try to take input as a directly a node\n if (typeof input === 'string' || input instanceof GraphNode) {\n input = {\n node: input\n };\n }\n\n if (typeof input.node === 'string') {\n for (var i = 0; i < this.nodes.length; i++) {\n var tmp = this.nodes[i];\n if (tmp.name === input.node) {\n node = tmp;\n }\n }\n }\n else {\n node = input.node;\n }\n if (node) {\n var inputPin = input.pin;\n if (!inputPin) {\n // Use first pin defaultly\n if (node.outputs) {\n inputPin = Object.keys(node.outputs)[0];\n }\n }\n if (node.outputs[inputPin]) {\n return {\n node: node,\n pin: inputPin\n };\n }\n }\n }\n});\n\nexport default Graph;\n","import Graph from './Graph';\nimport TexturePool from './TexturePool';\nimport FrameBuffer from '../FrameBuffer';\n\n/**\n * Compositor provide graph based post processing\n *\n * @constructor clay.compositor.Compositor\n * @extends clay.compositor.Graph\n *\n */\nvar Compositor = Graph.extend(function() {\n return {\n // Output node\n _outputs: [],\n\n _texturePool: new TexturePool(),\n\n _frameBuffer: new FrameBuffer({\n depthBuffer: false\n })\n };\n},\n/** @lends clay.compositor.Compositor.prototype */\n{\n addNode: function(node) {\n Graph.prototype.addNode.call(this, node);\n node._compositor = this;\n },\n /**\n * @param {clay.Renderer} renderer\n */\n render: function(renderer, frameBuffer) {\n if (this._dirty) {\n this.update();\n this._dirty = false;\n\n this._outputs.length = 0;\n for (var i = 0; i < this.nodes.length; i++) {\n if (!this.nodes[i].outputs) {\n this._outputs.push(this.nodes[i]);\n }\n }\n }\n\n for (var i = 0; i < this.nodes.length; i++) {\n // Update the reference number of each output texture\n this.nodes[i].beforeFrame();\n }\n\n for (var i = 0; i < this._outputs.length; i++) {\n this._outputs[i].updateReference();\n }\n\n for (var i = 0; i < this._outputs.length; i++) {\n this._outputs[i].render(renderer, frameBuffer);\n }\n\n for (var i = 0; i < this.nodes.length; i++) {\n // Clear up\n this.nodes[i].afterFrame();\n }\n },\n\n allocateTexture: function (parameters) {\n return this._texturePool.get(parameters);\n },\n\n releaseTexture: function (parameters) {\n this._texturePool.put(parameters);\n },\n\n getFrameBuffer: function () {\n return this._frameBuffer;\n },\n\n /**\n * Dispose compositor\n * @param {clay.Renderer} renderer\n */\n dispose: function (renderer) {\n this._texturePool.clear(renderer);\n }\n});\n\nexport default Compositor;\n","import CompositorNode from './CompositorNode';\nimport glenum from '../core/glenum';\nimport FrameBuffer from '../FrameBuffer';\n\n/**\n * @constructor clay.compositor.SceneNode\n * @extends clay.compositor.CompositorNode\n */\nvar SceneNode = CompositorNode.extend(\n/** @lends clay.compositor.SceneNode# */\n{\n name: 'scene',\n /**\n * @type {clay.Scene}\n */\n scene: null,\n /**\n * @type {clay.Camera}\n */\n camera: null,\n /**\n * @type {boolean}\n */\n autoUpdateScene: true,\n /**\n * @type {boolean}\n */\n preZ: false\n\n}, function() {\n this.frameBuffer = new FrameBuffer();\n}, {\n render: function(renderer) {\n\n this._rendering = true;\n var _gl = renderer.gl;\n\n this.trigger('beforerender');\n\n var renderInfo;\n\n if (!this.outputs) {\n\n renderInfo = renderer.render(this.scene, this.camera, !this.autoUpdateScene, this.preZ);\n\n }\n else {\n\n var frameBuffer = this.frameBuffer;\n for (var name in this.outputs) {\n var parameters = this.updateParameter(name, renderer);\n var outputInfo = this.outputs[name];\n var texture = this._compositor.allocateTexture(parameters);\n this._outputTextures[name] = texture;\n\n var attachment = outputInfo.attachment || _gl.COLOR_ATTACHMENT0;\n if (typeof(attachment) == 'string') {\n attachment = _gl[attachment];\n }\n frameBuffer.attach(texture, attachment);\n }\n frameBuffer.bind(renderer);\n\n // MRT Support in chrome\n // https://www.khronos.org/registry/webgl/sdk/tests/conformance/extensions/ext-draw-buffers.html\n var ext = renderer.getGLExtension('EXT_draw_buffers');\n if (ext) {\n var bufs = [];\n for (var attachment in this.outputs) {\n attachment = parseInt(attachment);\n if (attachment >= _gl.COLOR_ATTACHMENT0 && attachment <= _gl.COLOR_ATTACHMENT0 + 8) {\n bufs.push(attachment);\n }\n }\n ext.drawBuffersEXT(bufs);\n }\n\n // Always clear\n // PENDING\n renderer.saveClear();\n renderer.clearBit = glenum.DEPTH_BUFFER_BIT | glenum.COLOR_BUFFER_BIT;\n renderInfo = renderer.render(this.scene, this.camera, !this.autoUpdateScene, this.preZ);\n renderer.restoreClear();\n\n frameBuffer.unbind(renderer);\n }\n\n this.trigger('afterrender', renderInfo);\n\n this._rendering = false;\n this._rendered = true;\n }\n});\n\nexport default SceneNode;\n","import CompositorNode from './CompositorNode';\n\n/**\n * @constructor clay.compositor.TextureNode\n * @extends clay.compositor.CompositorNode\n */\nvar TextureNode = CompositorNode.extend(function() {\n return /** @lends clay.compositor.TextureNode# */ {\n /**\n * @type {clay.Texture2D}\n */\n texture: null,\n\n // Texture node must have output without parameters\n outputs: {\n color: {}\n }\n };\n}, function () {\n}, {\n\n getOutput: function (renderer, name) {\n return this.texture;\n },\n\n // Do nothing\n beforeFrame: function () {},\n afterFrame: function () {}\n});\n\nexport default TextureNode;\n","// TODO Shader library\nimport Pass from './Pass';\nimport CompositorNode from './CompositorNode';\n\n// TODO curlnoise demo wrong\n\n// PENDING\n// Use topological sort ?\n\n/**\n * Filter node\n *\n * @constructor clay.compositor.FilterNode\n * @extends clay.compositor.CompositorNode\n *\n * @example\n var node = new clay.compositor.FilterNode({\n name: 'fxaa',\n shader: clay.Shader.source('clay.compositor.fxaa'),\n inputs: {\n texture: {\n node: 'scene',\n pin: 'color'\n }\n },\n // Multiple outputs is preserved for MRT support in WebGL2.0\n outputs: {\n color: {\n attachment: clay.FrameBuffer.COLOR_ATTACHMENT0\n parameters: {\n format: clay.Texture.RGBA,\n width: 512,\n height: 512\n },\n // Node will keep the RTT rendered in last frame\n keepLastFrame: true,\n // Force the node output the RTT rendered in last frame\n outputLastFrame: true\n }\n }\n });\n *\n */\nvar FilterNode = CompositorNode.extend(function () {\n return /** @lends clay.compositor.FilterNode# */ {\n /**\n * @type {string}\n */\n name: '',\n\n /**\n * @type {Object}\n */\n inputs: {},\n\n /**\n * @type {Object}\n */\n outputs: null,\n\n /**\n * @type {string}\n */\n shader: '',\n\n /**\n * Input links, will be updated by the graph\n * @example:\n * inputName: {\n * node: someNode,\n * pin: 'xxxx'\n * }\n * @type {Object}\n */\n inputLinks: {},\n\n /**\n * Output links, will be updated by the graph\n * @example:\n * outputName: {\n * node: someNode,\n * pin: 'xxxx'\n * }\n * @type {Object}\n */\n outputLinks: {},\n\n /**\n * @type {clay.compositor.Pass}\n */\n pass: null,\n\n // Save the output texture of previous frame\n // Will be used when there exist a circular reference\n _prevOutputTextures: {},\n _outputTextures: {},\n\n // Example: { name: 2 }\n _outputReferences: {},\n\n _rendering: false,\n // If rendered in this frame\n _rendered: false,\n\n _compositor: null\n };\n}, function () {\n\n var pass = new Pass({\n fragment: this.shader\n });\n this.pass = pass;\n},\n/** @lends clay.compositor.FilterNode.prototype */\n{\n /**\n * @param {clay.Renderer} renderer\n */\n render: function (renderer, frameBuffer) {\n this.trigger('beforerender', renderer);\n\n this._rendering = true;\n\n var _gl = renderer.gl;\n\n for (var inputName in this.inputLinks) {\n var link = this.inputLinks[inputName];\n var inputTexture = link.node.getOutput(renderer, link.pin);\n this.pass.setUniform(inputName, inputTexture);\n }\n // Output\n if (!this.outputs) {\n this.pass.outputs = null;\n\n this._compositor.getFrameBuffer().unbind(renderer);\n\n this.pass.render(renderer, frameBuffer);\n }\n else {\n this.pass.outputs = {};\n\n var attachedTextures = {};\n for (var name in this.outputs) {\n var parameters = this.updateParameter(name, renderer);\n if (isNaN(parameters.width)) {\n this.updateParameter(name, renderer);\n }\n var outputInfo = this.outputs[name];\n var texture = this._compositor.allocateTexture(parameters);\n this._outputTextures[name] = texture;\n var attachment = outputInfo.attachment || _gl.COLOR_ATTACHMENT0;\n if (typeof(attachment) === 'string') {\n attachment = _gl[attachment];\n }\n attachedTextures[attachment] = texture;\n }\n this._compositor.getFrameBuffer().bind(renderer);\n\n for (var attachment in attachedTextures) {\n // FIXME attachment changes in different nodes\n this._compositor.getFrameBuffer().attach(\n attachedTextures[attachment], attachment\n );\n }\n\n this.pass.render(renderer);\n\n // Because the data of texture is changed over time,\n // Here update the mipmaps of texture each time after rendered;\n this._compositor.getFrameBuffer().updateMipmap(renderer);\n }\n\n for (var inputName in this.inputLinks) {\n var link = this.inputLinks[inputName];\n link.node.removeReference(link.pin);\n }\n\n this._rendering = false;\n this._rendered = true;\n\n this.trigger('afterrender', renderer);\n },\n\n // TODO Remove parameter function callback\n updateParameter: function (outputName, renderer) {\n var outputInfo = this.outputs[outputName];\n var parameters = outputInfo.parameters;\n var parametersCopy = outputInfo._parametersCopy;\n if (!parametersCopy) {\n parametersCopy = outputInfo._parametersCopy = {};\n }\n if (parameters) {\n for (var key in parameters) {\n if (key !== 'width' && key !== 'height') {\n parametersCopy[key] = parameters[key];\n }\n }\n }\n var width, height;\n if (typeof parameters.width === 'function') {\n width = parameters.width.call(this, renderer);\n }\n else {\n width = parameters.width;\n }\n if (typeof parameters.height === 'function') {\n height = parameters.height.call(this, renderer);\n }\n else {\n height = parameters.height;\n }\n width = Math.ceil(width);\n height = Math.ceil(height);\n if (\n parametersCopy.width !== width\n || parametersCopy.height !== height\n ) {\n if (this._outputTextures[outputName]) {\n this._outputTextures[outputName].dispose(renderer);\n }\n }\n parametersCopy.width = width;\n parametersCopy.height = height;\n\n return parametersCopy;\n },\n\n /**\n * Set parameter\n * @param {string} name\n * @param {} value\n */\n setParameter: function (name, value) {\n this.pass.setUniform(name, value);\n },\n /**\n * Get parameter value\n * @param {string} name\n * @return {}\n */\n getParameter: function (name) {\n return this.pass.getUniform(name);\n },\n /**\n * Set parameters\n * @param {Object} obj\n */\n setParameters: function (obj) {\n for (var name in obj) {\n this.setParameter(name, obj[name]);\n }\n },\n // /**\n // * Set shader code\n // * @param {string} shaderStr\n // */\n // setShader: function (shaderStr) {\n // var material = this.pass.material;\n // material.shader.setFragment(shaderStr);\n // material.attachShader(material.shader, true);\n // },\n /**\n * Proxy of pass.material.define('fragment', xxx);\n * @param {string} symbol\n * @param {number} [val]\n */\n define: function (symbol, val) {\n this.pass.material.define('fragment', symbol, val);\n },\n\n /**\n * Proxy of pass.material.undefine('fragment', xxx)\n * @param {string} symbol\n */\n undefine: function (symbol) {\n this.pass.material.undefine('fragment', symbol);\n },\n\n removeReference: function (outputName) {\n this._outputReferences[outputName]--;\n if (this._outputReferences[outputName] === 0) {\n var outputInfo = this.outputs[outputName];\n if (outputInfo.keepLastFrame) {\n if (this._prevOutputTextures[outputName]) {\n this._compositor.releaseTexture(this._prevOutputTextures[outputName]);\n }\n this._prevOutputTextures[outputName] = this._outputTextures[outputName];\n }\n else {\n // Output of this node have alreay been used by all other nodes\n // Put the texture back to the pool.\n this._compositor.releaseTexture(this._outputTextures[outputName]);\n }\n }\n },\n\n clear: function () {\n CompositorNode.prototype.clear.call(this);\n\n // Default disable all texture\n this.pass.material.disableTexturesAll();\n }\n});\n\nexport default FilterNode;\n","export default \"@export clay.compositor.coloradjust\\nvarying vec2 v_Texcoord;\\nuniform sampler2D texture;\\nuniform float brightness : 0.0;\\nuniform float contrast : 1.0;\\nuniform float exposure : 0.0;\\nuniform float gamma : 1.0;\\nuniform float saturation : 1.0;\\nconst vec3 w = vec3(0.2125, 0.7154, 0.0721);\\nvoid main()\\n{\\n vec4 tex = texture2D( texture, v_Texcoord);\\n vec3 color = clamp(tex.rgb + vec3(brightness), 0.0, 1.0);\\n color = clamp( (color-vec3(0.5))*contrast+vec3(0.5), 0.0, 1.0);\\n color = clamp( color * pow(2.0, exposure), 0.0, 1.0);\\n color = clamp( pow(color, vec3(gamma)), 0.0, 1.0);\\n float luminance = dot( color, w );\\n color = mix(vec3(luminance), color, saturation);\\n gl_FragColor = vec4(color, tex.a);\\n}\\n@end\\n@export clay.compositor.brightness\\nvarying vec2 v_Texcoord;\\nuniform sampler2D texture;\\nuniform float brightness : 0.0;\\nvoid main()\\n{\\n vec4 tex = texture2D( texture, v_Texcoord);\\n vec3 color = tex.rgb + vec3(brightness);\\n gl_FragColor = vec4(color, tex.a);\\n}\\n@end\\n@export clay.compositor.contrast\\nvarying vec2 v_Texcoord;\\nuniform sampler2D texture;\\nuniform float contrast : 1.0;\\nvoid main()\\n{\\n vec4 tex = texture2D( texture, v_Texcoord);\\n vec3 color = (tex.rgb-vec3(0.5))*contrast+vec3(0.5);\\n gl_FragColor = vec4(color, tex.a);\\n}\\n@end\\n@export clay.compositor.exposure\\nvarying vec2 v_Texcoord;\\nuniform sampler2D texture;\\nuniform float exposure : 0.0;\\nvoid main()\\n{\\n vec4 tex = texture2D(texture, v_Texcoord);\\n vec3 color = tex.rgb * pow(2.0, exposure);\\n gl_FragColor = vec4(color, tex.a);\\n}\\n@end\\n@export clay.compositor.gamma\\nvarying vec2 v_Texcoord;\\nuniform sampler2D texture;\\nuniform float gamma : 1.0;\\nvoid main()\\n{\\n vec4 tex = texture2D(texture, v_Texcoord);\\n vec3 color = pow(tex.rgb, vec3(gamma));\\n gl_FragColor = vec4(color, tex.a);\\n}\\n@end\\n@export clay.compositor.saturation\\nvarying vec2 v_Texcoord;\\nuniform sampler2D texture;\\nuniform float saturation : 1.0;\\nconst vec3 w = vec3(0.2125, 0.7154, 0.0721);\\nvoid main()\\n{\\n vec4 tex = texture2D(texture, v_Texcoord);\\n vec3 color = tex.rgb;\\n float luminance = dot(color, w);\\n color = mix(vec3(luminance), color, saturation);\\n gl_FragColor = vec4(color, tex.a);\\n}\\n@end\";\n","export default \"@export clay.compositor.kernel.gaussian_9\\nfloat gaussianKernel[9];\\ngaussianKernel[0] = 0.07;\\ngaussianKernel[1] = 0.09;\\ngaussianKernel[2] = 0.12;\\ngaussianKernel[3] = 0.14;\\ngaussianKernel[4] = 0.16;\\ngaussianKernel[5] = 0.14;\\ngaussianKernel[6] = 0.12;\\ngaussianKernel[7] = 0.09;\\ngaussianKernel[8] = 0.07;\\n@end\\n@export clay.compositor.kernel.gaussian_13\\nfloat gaussianKernel[13];\\ngaussianKernel[0] = 0.02;\\ngaussianKernel[1] = 0.03;\\ngaussianKernel[2] = 0.06;\\ngaussianKernel[3] = 0.08;\\ngaussianKernel[4] = 0.11;\\ngaussianKernel[5] = 0.13;\\ngaussianKernel[6] = 0.14;\\ngaussianKernel[7] = 0.13;\\ngaussianKernel[8] = 0.11;\\ngaussianKernel[9] = 0.08;\\ngaussianKernel[10] = 0.06;\\ngaussianKernel[11] = 0.03;\\ngaussianKernel[12] = 0.02;\\n@end\\n@export clay.compositor.gaussian_blur\\n#define SHADER_NAME gaussian_blur\\nuniform sampler2D texture;varying vec2 v_Texcoord;\\nuniform float blurSize : 2.0;\\nuniform vec2 textureSize : [512.0, 512.0];\\nuniform float blurDir : 0.0;\\n@import clay.util.rgbm\\n@import clay.util.clamp_sample\\nvoid main (void)\\n{\\n @import clay.compositor.kernel.gaussian_9\\n vec2 off = blurSize / textureSize;\\n off *= vec2(1.0 - blurDir, blurDir);\\n vec4 sum = vec4(0.0);\\n float weightAll = 0.0;\\n for (int i = 0; i < 9; i++) {\\n float w = gaussianKernel[i];\\n vec4 texel = decodeHDR(clampSample(texture, v_Texcoord + float(i - 4) * off));\\n sum += texel * w;\\n weightAll += w;\\n }\\n gl_FragColor = encodeHDR(sum / max(weightAll, 0.01));\\n}\\n@end\\n\";\n","export default \"@export clay.compositor.hdr.log_lum\\nvarying vec2 v_Texcoord;\\nuniform sampler2D texture;\\nconst vec3 w = vec3(0.2125, 0.7154, 0.0721);\\n@import clay.util.rgbm\\nvoid main()\\n{\\n vec4 tex = decodeHDR(texture2D(texture, v_Texcoord));\\n float luminance = dot(tex.rgb, w);\\n luminance = log(luminance + 0.001);\\n gl_FragColor = encodeHDR(vec4(vec3(luminance), 1.0));\\n}\\n@end\\n@export clay.compositor.hdr.lum_adaption\\nvarying vec2 v_Texcoord;\\nuniform sampler2D adaptedLum;\\nuniform sampler2D currentLum;\\nuniform float frameTime : 0.02;\\n@import clay.util.rgbm\\nvoid main()\\n{\\n float fAdaptedLum = decodeHDR(texture2D(adaptedLum, vec2(0.5, 0.5))).r;\\n float fCurrentLum = exp(encodeHDR(texture2D(currentLum, vec2(0.5, 0.5))).r);\\n fAdaptedLum += (fCurrentLum - fAdaptedLum) * (1.0 - pow(0.98, 30.0 * frameTime));\\n gl_FragColor = encodeHDR(vec4(vec3(fAdaptedLum), 1.0));\\n}\\n@end\\n@export clay.compositor.lum\\nvarying vec2 v_Texcoord;\\nuniform sampler2D texture;\\nconst vec3 w = vec3(0.2125, 0.7154, 0.0721);\\nvoid main()\\n{\\n vec4 tex = texture2D( texture, v_Texcoord );\\n float luminance = dot(tex.rgb, w);\\n gl_FragColor = vec4(vec3(luminance), 1.0);\\n}\\n@end\";\n","export default \"\\n@export clay.compositor.lut\\nvarying vec2 v_Texcoord;\\nuniform sampler2D texture;\\nuniform sampler2D lookup;\\nvoid main()\\n{\\n vec4 tex = texture2D(texture, v_Texcoord);\\n float blueColor = tex.b * 63.0;\\n vec2 quad1;\\n quad1.y = floor(floor(blueColor) / 8.0);\\n quad1.x = floor(blueColor) - (quad1.y * 8.0);\\n vec2 quad2;\\n quad2.y = floor(ceil(blueColor) / 8.0);\\n quad2.x = ceil(blueColor) - (quad2.y * 8.0);\\n vec2 texPos1;\\n texPos1.x = (quad1.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * tex.r);\\n texPos1.y = (quad1.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * tex.g);\\n vec2 texPos2;\\n texPos2.x = (quad2.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * tex.r);\\n texPos2.y = (quad2.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * tex.g);\\n vec4 newColor1 = texture2D(lookup, texPos1);\\n vec4 newColor2 = texture2D(lookup, texPos2);\\n vec4 newColor = mix(newColor1, newColor2, fract(blueColor));\\n gl_FragColor = vec4(newColor.rgb, tex.w);\\n}\\n@end\";\n","export default \"@export clay.compositor.vignette\\n#define OUTPUT_ALPHA\\nvarying vec2 v_Texcoord;\\nuniform sampler2D texture;\\nuniform float darkness: 1;\\nuniform float offset: 1;\\n@import clay.util.rgbm\\nvoid main()\\n{\\n vec4 texel = decodeHDR(texture2D(texture, v_Texcoord));\\n gl_FragColor.rgb = texel.rgb;\\n vec2 uv = (v_Texcoord - vec2(0.5)) * vec2(offset);\\n gl_FragColor = encodeHDR(vec4(mix(texel.rgb, vec3(1.0 - darkness), dot(uv, uv)), texel.a));\\n}\\n@end\";\n","export default \"@export clay.compositor.output\\n#define OUTPUT_ALPHA\\nvarying vec2 v_Texcoord;\\nuniform sampler2D texture;\\n@import clay.util.rgbm\\nvoid main()\\n{\\n vec4 tex = decodeHDR(texture2D(texture, v_Texcoord));\\n gl_FragColor.rgb = tex.rgb;\\n#ifdef OUTPUT_ALPHA\\n gl_FragColor.a = tex.a;\\n#else\\n gl_FragColor.a = 1.0;\\n#endif\\n gl_FragColor = encodeHDR(gl_FragColor);\\n#ifdef PREMULTIPLY_ALPHA\\n gl_FragColor.rgb *= gl_FragColor.a;\\n#endif\\n}\\n@end\";\n","export default \"@export clay.compositor.bright\\nuniform sampler2D texture;\\nuniform float threshold : 1;\\nuniform float scale : 1.0;\\nuniform vec2 textureSize: [512, 512];\\nvarying vec2 v_Texcoord;\\nconst vec3 lumWeight = vec3(0.2125, 0.7154, 0.0721);\\n@import clay.util.rgbm\\nvec4 median(vec4 a, vec4 b, vec4 c)\\n{\\n return a + b + c - min(min(a, b), c) - max(max(a, b), c);\\n}\\nvoid main()\\n{\\n vec4 texel = decodeHDR(texture2D(texture, v_Texcoord));\\n#ifdef ANTI_FLICKER\\n vec3 d = 1.0 / textureSize.xyx * vec3(1.0, 1.0, 0.0);\\n vec4 s1 = decodeHDR(texture2D(texture, v_Texcoord - d.xz));\\n vec4 s2 = decodeHDR(texture2D(texture, v_Texcoord + d.xz));\\n vec4 s3 = decodeHDR(texture2D(texture, v_Texcoord - d.zy));\\n vec4 s4 = decodeHDR(texture2D(texture, v_Texcoord + d.zy));\\n texel = median(median(texel, s1, s2), s3, s4);\\n#endif\\n float lum = dot(texel.rgb , lumWeight);\\n vec4 color;\\n if (lum > threshold && texel.a > 0.0)\\n {\\n color = vec4(texel.rgb * scale, texel.a * scale);\\n }\\n else\\n {\\n color = vec4(0.0);\\n }\\n gl_FragColor = encodeHDR(color);\\n}\\n@end\\n\";\n","export default \"@export clay.compositor.downsample\\nuniform sampler2D texture;\\nuniform vec2 textureSize : [512, 512];\\nvarying vec2 v_Texcoord;\\n@import clay.util.rgbm\\nfloat brightness(vec3 c)\\n{\\n return max(max(c.r, c.g), c.b);\\n}\\n@import clay.util.clamp_sample\\nvoid main()\\n{\\n vec4 d = vec4(-1.0, -1.0, 1.0, 1.0) / textureSize.xyxy;\\n#ifdef ANTI_FLICKER\\n vec3 s1 = decodeHDR(clampSample(texture, v_Texcoord + d.xy)).rgb;\\n vec3 s2 = decodeHDR(clampSample(texture, v_Texcoord + d.zy)).rgb;\\n vec3 s3 = decodeHDR(clampSample(texture, v_Texcoord + d.xw)).rgb;\\n vec3 s4 = decodeHDR(clampSample(texture, v_Texcoord + d.zw)).rgb;\\n float s1w = 1.0 / (brightness(s1) + 1.0);\\n float s2w = 1.0 / (brightness(s2) + 1.0);\\n float s3w = 1.0 / (brightness(s3) + 1.0);\\n float s4w = 1.0 / (brightness(s4) + 1.0);\\n float oneDivideSum = 1.0 / (s1w + s2w + s3w + s4w);\\n vec4 color = vec4(\\n (s1 * s1w + s2 * s2w + s3 * s3w + s4 * s4w) * oneDivideSum,\\n 1.0\\n );\\n#else\\n vec4 color = decodeHDR(clampSample(texture, v_Texcoord + d.xy));\\n color += decodeHDR(clampSample(texture, v_Texcoord + d.zy));\\n color += decodeHDR(clampSample(texture, v_Texcoord + d.xw));\\n color += decodeHDR(clampSample(texture, v_Texcoord + d.zw));\\n color *= 0.25;\\n#endif\\n gl_FragColor = encodeHDR(color);\\n}\\n@end\";\n","export default \"\\n@export clay.compositor.upsample\\n#define HIGH_QUALITY\\nuniform sampler2D texture;\\nuniform vec2 textureSize : [512, 512];\\nuniform float sampleScale: 0.5;\\nvarying vec2 v_Texcoord;\\n@import clay.util.rgbm\\n@import clay.util.clamp_sample\\nvoid main()\\n{\\n#ifdef HIGH_QUALITY\\n vec4 d = vec4(1.0, 1.0, -1.0, 0.0) / textureSize.xyxy * sampleScale;\\n vec4 s;\\n s = decodeHDR(clampSample(texture, v_Texcoord - d.xy));\\n s += decodeHDR(clampSample(texture, v_Texcoord - d.wy)) * 2.0;\\n s += decodeHDR(clampSample(texture, v_Texcoord - d.zy));\\n s += decodeHDR(clampSample(texture, v_Texcoord + d.zw)) * 2.0;\\n s += decodeHDR(clampSample(texture, v_Texcoord )) * 4.0;\\n s += decodeHDR(clampSample(texture, v_Texcoord + d.xw)) * 2.0;\\n s += decodeHDR(clampSample(texture, v_Texcoord + d.zy));\\n s += decodeHDR(clampSample(texture, v_Texcoord + d.wy)) * 2.0;\\n s += decodeHDR(clampSample(texture, v_Texcoord + d.xy));\\n gl_FragColor = encodeHDR(s / 16.0);\\n#else\\n vec4 d = vec4(-1.0, -1.0, +1.0, +1.0) / textureSize.xyxy;\\n vec4 s;\\n s = decodeHDR(clampSample(texture, v_Texcoord + d.xy));\\n s += decodeHDR(clampSample(texture, v_Texcoord + d.zy));\\n s += decodeHDR(clampSample(texture, v_Texcoord + d.xw));\\n s += decodeHDR(clampSample(texture, v_Texcoord + d.zw));\\n gl_FragColor = encodeHDR(s / 4.0);\\n#endif\\n}\\n@end\";\n","export default \"@export clay.compositor.hdr.composite\\n#define TONEMAPPING\\nuniform sampler2D texture;\\n#ifdef BLOOM_ENABLED\\nuniform sampler2D bloom;\\n#endif\\n#ifdef LENSFLARE_ENABLED\\nuniform sampler2D lensflare;\\nuniform sampler2D lensdirt;\\n#endif\\n#ifdef LUM_ENABLED\\nuniform sampler2D lum;\\n#endif\\n#ifdef LUT_ENABLED\\nuniform sampler2D lut;\\n#endif\\n#ifdef COLOR_CORRECTION\\nuniform float brightness : 0.0;\\nuniform float contrast : 1.0;\\nuniform float saturation : 1.0;\\n#endif\\n#ifdef VIGNETTE\\nuniform float vignetteDarkness: 1.0;\\nuniform float vignetteOffset: 1.0;\\n#endif\\nuniform float exposure : 1.0;\\nuniform float bloomIntensity : 0.25;\\nuniform float lensflareIntensity : 1;\\nvarying vec2 v_Texcoord;\\n@import clay.util.srgb\\nvec3 ACESToneMapping(vec3 color)\\n{\\n const float A = 2.51;\\n const float B = 0.03;\\n const float C = 2.43;\\n const float D = 0.59;\\n const float E = 0.14;\\n return (color * (A * color + B)) / (color * (C * color + D) + E);\\n}\\nfloat eyeAdaption(float fLum)\\n{\\n return mix(0.2, fLum, 0.5);\\n}\\n#ifdef LUT_ENABLED\\nvec3 lutTransform(vec3 color) {\\n float blueColor = color.b * 63.0;\\n vec2 quad1;\\n quad1.y = floor(floor(blueColor) / 8.0);\\n quad1.x = floor(blueColor) - (quad1.y * 8.0);\\n vec2 quad2;\\n quad2.y = floor(ceil(blueColor) / 8.0);\\n quad2.x = ceil(blueColor) - (quad2.y * 8.0);\\n vec2 texPos1;\\n texPos1.x = (quad1.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * color.r);\\n texPos1.y = (quad1.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * color.g);\\n vec2 texPos2;\\n texPos2.x = (quad2.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * color.r);\\n texPos2.y = (quad2.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * color.g);\\n vec4 newColor1 = texture2D(lut, texPos1);\\n vec4 newColor2 = texture2D(lut, texPos2);\\n vec4 newColor = mix(newColor1, newColor2, fract(blueColor));\\n return newColor.rgb;\\n}\\n#endif\\n@import clay.util.rgbm\\nvoid main()\\n{\\n vec4 texel = vec4(0.0);\\n vec4 originalTexel = vec4(0.0);\\n#ifdef TEXTURE_ENABLED\\n texel = decodeHDR(texture2D(texture, v_Texcoord));\\n originalTexel = texel;\\n#endif\\n#ifdef BLOOM_ENABLED\\n vec4 bloomTexel = decodeHDR(texture2D(bloom, v_Texcoord));\\n texel.rgb += bloomTexel.rgb * bloomIntensity;\\n texel.a += bloomTexel.a * bloomIntensity;\\n#endif\\n#ifdef LENSFLARE_ENABLED\\n texel += decodeHDR(texture2D(lensflare, v_Texcoord)) * texture2D(lensdirt, v_Texcoord) * lensflareIntensity;\\n#endif\\n texel.a = min(texel.a, 1.0);\\n#ifdef LUM_ENABLED\\n float fLum = texture2D(lum, vec2(0.5, 0.5)).r;\\n float adaptedLumDest = 3.0 / (max(0.1, 1.0 + 10.0*eyeAdaption(fLum)));\\n float exposureBias = adaptedLumDest * exposure;\\n#else\\n float exposureBias = exposure;\\n#endif\\n#ifdef TONEMAPPING\\n texel.rgb *= exposureBias;\\n texel.rgb = ACESToneMapping(texel.rgb);\\n#endif\\n texel = linearTosRGB(texel);\\n#ifdef LUT_ENABLED\\n texel.rgb = lutTransform(clamp(texel.rgb,vec3(0.0),vec3(1.0)));\\n#endif\\n#ifdef COLOR_CORRECTION\\n texel.rgb = clamp(texel.rgb + vec3(brightness), 0.0, 1.0);\\n texel.rgb = clamp((texel.rgb - vec3(0.5))*contrast+vec3(0.5), 0.0, 1.0);\\n float lum = dot(texel.rgb, vec3(0.2125, 0.7154, 0.0721));\\n texel.rgb = mix(vec3(lum), texel.rgb, saturation);\\n#endif\\n#ifdef VIGNETTE\\n vec2 uv = (v_Texcoord - vec2(0.5)) * vec2(vignetteOffset);\\n texel.rgb = mix(texel.rgb, vec3(1.0 - vignetteDarkness), dot(uv, uv));\\n#endif\\n gl_FragColor = encodeHDR(texel);\\n#ifdef DEBUG\\n #if DEBUG == 1\\n gl_FragColor = encodeHDR(decodeHDR(texture2D(texture, v_Texcoord)));\\n #elif DEBUG == 2\\n gl_FragColor = encodeHDR(decodeHDR(texture2D(bloom, v_Texcoord)) * bloomIntensity);\\n #elif DEBUG == 3\\n gl_FragColor = encodeHDR(decodeHDR(texture2D(lensflare, v_Texcoord) * lensflareIntensity));\\n #endif\\n#endif\\n if (originalTexel.a <= 0.01 && gl_FragColor.a > 1e-5) {\\n gl_FragColor.a = dot(gl_FragColor.rgb, vec3(0.2125, 0.7154, 0.0721));\\n }\\n#ifdef PREMULTIPLY_ALPHA\\n gl_FragColor.rgb *= gl_FragColor.a;\\n#endif\\n}\\n@end\";\n","export default \"@export clay.compositor.lensflare\\n#define SAMPLE_NUMBER 8\\nuniform sampler2D texture;\\nuniform sampler2D lenscolor;\\nuniform vec2 textureSize : [512, 512];\\nuniform float dispersal : 0.3;\\nuniform float haloWidth : 0.4;\\nuniform float distortion : 1.0;\\nvarying vec2 v_Texcoord;\\n@import clay.util.rgbm\\nvec4 textureDistorted(\\n in vec2 texcoord,\\n in vec2 direction,\\n in vec3 distortion\\n) {\\n return vec4(\\n decodeHDR(texture2D(texture, texcoord + direction * distortion.r)).r,\\n decodeHDR(texture2D(texture, texcoord + direction * distortion.g)).g,\\n decodeHDR(texture2D(texture, texcoord + direction * distortion.b)).b,\\n 1.0\\n );\\n}\\nvoid main()\\n{\\n vec2 texcoord = -v_Texcoord + vec2(1.0); vec2 textureOffset = 1.0 / textureSize;\\n vec2 ghostVec = (vec2(0.5) - texcoord) * dispersal;\\n vec2 haloVec = normalize(ghostVec) * haloWidth;\\n vec3 distortion = vec3(-textureOffset.x * distortion, 0.0, textureOffset.x * distortion);\\n vec4 result = vec4(0.0);\\n for (int i = 0; i < SAMPLE_NUMBER; i++)\\n {\\n vec2 offset = fract(texcoord + ghostVec * float(i));\\n float weight = length(vec2(0.5) - offset) / length(vec2(0.5));\\n weight = pow(1.0 - weight, 10.0);\\n result += textureDistorted(offset, normalize(ghostVec), distortion) * weight;\\n }\\n result *= texture2D(lenscolor, vec2(length(vec2(0.5) - texcoord)) / length(vec2(0.5)));\\n float weight = length(vec2(0.5) - fract(texcoord + haloVec)) / length(vec2(0.5));\\n weight = pow(1.0 - weight, 10.0);\\n vec2 offset = fract(texcoord + haloVec);\\n result += textureDistorted(offset, normalize(ghostVec), distortion) * weight;\\n gl_FragColor = result;\\n}\\n@end\";\n","export default \"@export clay.compositor.blend\\n#define SHADER_NAME blend\\n#ifdef TEXTURE1_ENABLED\\nuniform sampler2D texture1;\\nuniform float weight1 : 1.0;\\n#endif\\n#ifdef TEXTURE2_ENABLED\\nuniform sampler2D texture2;\\nuniform float weight2 : 1.0;\\n#endif\\n#ifdef TEXTURE3_ENABLED\\nuniform sampler2D texture3;\\nuniform float weight3 : 1.0;\\n#endif\\n#ifdef TEXTURE4_ENABLED\\nuniform sampler2D texture4;\\nuniform float weight4 : 1.0;\\n#endif\\n#ifdef TEXTURE5_ENABLED\\nuniform sampler2D texture5;\\nuniform float weight5 : 1.0;\\n#endif\\n#ifdef TEXTURE6_ENABLED\\nuniform sampler2D texture6;\\nuniform float weight6 : 1.0;\\n#endif\\nvarying vec2 v_Texcoord;\\n@import clay.util.rgbm\\nvoid main()\\n{\\n vec4 tex = vec4(0.0);\\n#ifdef TEXTURE1_ENABLED\\n tex += decodeHDR(texture2D(texture1, v_Texcoord)) * weight1;\\n#endif\\n#ifdef TEXTURE2_ENABLED\\n tex += decodeHDR(texture2D(texture2, v_Texcoord)) * weight2;\\n#endif\\n#ifdef TEXTURE3_ENABLED\\n tex += decodeHDR(texture2D(texture3, v_Texcoord)) * weight3;\\n#endif\\n#ifdef TEXTURE4_ENABLED\\n tex += decodeHDR(texture2D(texture4, v_Texcoord)) * weight4;\\n#endif\\n#ifdef TEXTURE5_ENABLED\\n tex += decodeHDR(texture2D(texture5, v_Texcoord)) * weight5;\\n#endif\\n#ifdef TEXTURE6_ENABLED\\n tex += decodeHDR(texture2D(texture6, v_Texcoord)) * weight6;\\n#endif\\n gl_FragColor = encodeHDR(tex);\\n}\\n@end\";\n","export default \"@export clay.compositor.fxaa\\nuniform sampler2D texture;\\nuniform vec4 viewport : VIEWPORT;\\nvarying vec2 v_Texcoord;\\n#define FXAA_REDUCE_MIN (1.0/128.0)\\n#define FXAA_REDUCE_MUL (1.0/8.0)\\n#define FXAA_SPAN_MAX 8.0\\n@import clay.util.rgbm\\nvoid main()\\n{\\n vec2 resolution = 1.0 / viewport.zw;\\n vec3 rgbNW = decodeHDR( texture2D( texture, ( gl_FragCoord.xy + vec2( -1.0, -1.0 ) ) * resolution ) ).xyz;\\n vec3 rgbNE = decodeHDR( texture2D( texture, ( gl_FragCoord.xy + vec2( 1.0, -1.0 ) ) * resolution ) ).xyz;\\n vec3 rgbSW = decodeHDR( texture2D( texture, ( gl_FragCoord.xy + vec2( -1.0, 1.0 ) ) * resolution ) ).xyz;\\n vec3 rgbSE = decodeHDR( texture2D( texture, ( gl_FragCoord.xy + vec2( 1.0, 1.0 ) ) * resolution ) ).xyz;\\n vec4 rgbaM = decodeHDR( texture2D( texture, gl_FragCoord.xy * resolution ) );\\n vec3 rgbM = rgbaM.xyz;\\n float opacity = rgbaM.w;\\n vec3 luma = vec3( 0.299, 0.587, 0.114 );\\n float lumaNW = dot( rgbNW, luma );\\n float lumaNE = dot( rgbNE, luma );\\n float lumaSW = dot( rgbSW, luma );\\n float lumaSE = dot( rgbSE, luma );\\n float lumaM = dot( rgbM, luma );\\n float lumaMin = min( lumaM, min( min( lumaNW, lumaNE ), min( lumaSW, lumaSE ) ) );\\n float lumaMax = max( lumaM, max( max( lumaNW, lumaNE) , max( lumaSW, lumaSE ) ) );\\n vec2 dir;\\n dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));\\n dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));\\n float dirReduce = max( ( lumaNW + lumaNE + lumaSW + lumaSE ) * ( 0.25 * FXAA_REDUCE_MUL ), FXAA_REDUCE_MIN );\\n float rcpDirMin = 1.0 / ( min( abs( dir.x ), abs( dir.y ) ) + dirReduce );\\n dir = min( vec2( FXAA_SPAN_MAX, FXAA_SPAN_MAX),\\n max( vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),\\n dir * rcpDirMin)) * resolution;\\n vec3 rgbA = decodeHDR( texture2D( texture, gl_FragCoord.xy * resolution + dir * ( 1.0 / 3.0 - 0.5 ) ) ).xyz;\\n rgbA += decodeHDR( texture2D( texture, gl_FragCoord.xy * resolution + dir * ( 2.0 / 3.0 - 0.5 ) ) ).xyz;\\n rgbA *= 0.5;\\n vec3 rgbB = decodeHDR( texture2D( texture, gl_FragCoord.xy * resolution + dir * -0.5 ) ).xyz;\\n rgbB += decodeHDR( texture2D( texture, gl_FragCoord.xy * resolution + dir * 0.5 ) ).xyz;\\n rgbB *= 0.25;\\n rgbB += rgbA * 0.5;\\n float lumaB = dot( rgbB, luma );\\n if ( ( lumaB < lumaMin ) || ( lumaB > lumaMax ) )\\n {\\n gl_FragColor = vec4( rgbA, opacity );\\n }\\n else {\\n gl_FragColor = vec4( rgbB, opacity );\\n }\\n}\\n@end\";\n","import coloradjustEssl from './source/compositor/coloradjust.glsl.js';\nimport blurEssl from './source/compositor/blur.glsl.js';\nimport lumEssl from './source/compositor/lum.glsl.js';\nimport lutEssl from './source/compositor/lut.glsl.js';\nimport vigentteEssl from './source/compositor/vignette.glsl.js';\nimport outputEssl from './source/compositor/output.glsl.js';\nimport brightEssl from './source/compositor/bright.glsl.js';\nimport downsampleEssl from './source/compositor/downsample.glsl.js';\nimport upsampleEssl from './source/compositor/upsample.glsl.js';\nimport hdrEssl from './source/compositor/hdr.glsl.js';\nimport lensflareEssl from './source/compositor/lensflare.glsl.js';\nimport blendEssl from './source/compositor/blend.glsl.js';\nimport fxaaEssl from './source/compositor/fxaa.glsl.js';\n// import fxaa3Essl from './source/compositor/fxaa3.glsl.js';\n\n// TODO Must export a module and be used in the other modules. Or it will be tree shaked\nexport default function register(Shader) {\n // Some build in shaders\n Shader['import'](coloradjustEssl);\n Shader['import'](blurEssl);\n Shader['import'](lumEssl);\n Shader['import'](lutEssl);\n Shader['import'](vigentteEssl);\n Shader['import'](outputEssl);\n Shader['import'](brightEssl);\n Shader['import'](downsampleEssl);\n Shader['import'](upsampleEssl);\n Shader['import'](hdrEssl);\n Shader['import'](lensflareEssl);\n Shader['import'](blendEssl);\n\n Shader['import'](fxaaEssl);\n\n}","import util from './core/util';\nimport Compositor from './compositor/Compositor';\nimport CompoSceneNode from './compositor/SceneNode';\nimport CompoTextureNode from './compositor/TextureNode';\nimport CompoFilterNode from './compositor/FilterNode';\nimport Shader from './Shader';\nimport Texture from './Texture';\nimport Texture2D from './Texture2D';\nimport TextureCube from './TextureCube';\n\nimport registerBuiltinCompositor from './shader/registerBuiltinCompositor';\n\nregisterBuiltinCompositor(Shader);\n\nvar shaderSourceReg = /^#source\\((.*?)\\)/;\n\n/**\n * @name clay.createCompositor\n * @function\n * @param {Object} json\n * @param {Object} [opts]\n * @return {clay.compositor.Compositor}\n */\nfunction createCompositor(json, opts) {\n var compositor = new Compositor();\n opts = opts || {};\n\n var lib = {\n textures: {},\n parameters: {}\n };\n var afterLoad = function(shaderLib, textureLib) {\n for (var i = 0; i < json.nodes.length; i++) {\n var nodeInfo = json.nodes[i];\n var node = createNode(nodeInfo, lib, opts);\n if (node) {\n compositor.addNode(node);\n }\n }\n };\n\n for (var name in json.parameters) {\n var paramInfo = json.parameters[name];\n lib.parameters[name] = convertParameter(paramInfo);\n }\n // TODO load texture asynchronous\n loadTextures(json, lib, opts, function(textureLib) {\n lib.textures = textureLib;\n afterLoad();\n });\n\n return compositor;\n}\n\nfunction createNode(nodeInfo, lib, opts) {\n var type = nodeInfo.type || 'filter';\n var shaderSource;\n var inputs;\n var outputs;\n\n if (type === 'filter') {\n var shaderExp = nodeInfo.shader.trim();\n var res = shaderSourceReg.exec(shaderExp);\n if (res) {\n shaderSource = Shader.source(res[1].trim());\n }\n else if (shaderExp.charAt(0) === '#') {\n shaderSource = lib.shaders[shaderExp.substr(1)];\n }\n if (!shaderSource) {\n shaderSource = shaderExp;\n }\n if (!shaderSource) {\n return;\n }\n }\n\n if (nodeInfo.inputs) {\n inputs = {};\n for (var name in nodeInfo.inputs) {\n if (typeof nodeInfo.inputs[name] === 'string') {\n inputs[name] = nodeInfo.inputs[name];\n }\n else {\n inputs[name] = {\n node: nodeInfo.inputs[name].node,\n pin: nodeInfo.inputs[name].pin\n };\n }\n }\n }\n if (nodeInfo.outputs) {\n outputs = {};\n for (var name in nodeInfo.outputs) {\n var outputInfo = nodeInfo.outputs[name];\n outputs[name] = {};\n if (outputInfo.attachment != null) {\n outputs[name].attachment = outputInfo.attachment;\n }\n if (outputInfo.keepLastFrame != null) {\n outputs[name].keepLastFrame = outputInfo.keepLastFrame;\n }\n if (outputInfo.outputLastFrame != null) {\n outputs[name].outputLastFrame = outputInfo.outputLastFrame;\n }\n if (outputInfo.parameters) {\n outputs[name].parameters = convertParameter(outputInfo.parameters);\n }\n }\n }\n var node;\n if (type === 'scene') {\n node = new CompoSceneNode({\n name: nodeInfo.name,\n scene: opts.scene,\n camera: opts.camera,\n outputs: outputs\n });\n }\n else if (type === 'texture') {\n node = new CompoTextureNode({\n name: nodeInfo.name,\n outputs: outputs\n });\n }\n // Default is filter\n else {\n node = new CompoFilterNode({\n name: nodeInfo.name,\n shader: shaderSource,\n inputs: inputs,\n outputs: outputs\n });\n }\n if (node) {\n if (nodeInfo.parameters) {\n for (var name in nodeInfo.parameters) {\n var val = nodeInfo.parameters[name];\n if (typeof val === 'string') {\n val = val.trim();\n if (val.charAt(0) === '#') {\n val = lib.textures[val.substr(1)];\n }\n else {\n node.on(\n 'beforerender', createSizeSetHandler(\n name, tryConvertExpr(val)\n )\n );\n }\n }\n else if (typeof val === 'function') {\n node.on('beforerender', val);\n }\n node.setParameter(name, val);\n }\n }\n if (nodeInfo.defines && node.pass) {\n for (var name in nodeInfo.defines) {\n var val = nodeInfo.defines[name];\n node.pass.material.define('fragment', name, val);\n }\n }\n }\n return node;\n}\n\nfunction defaultWidthFunc(width, height) {\n return width;\n}\nfunction defaultHeightFunc(width, height) {\n return height;\n}\n\nfunction convertParameter(paramInfo) {\n var param = {};\n if (!paramInfo) {\n return param;\n }\n ['type', 'minFilter', 'magFilter', 'wrapS', 'wrapT', 'flipY', 'useMipmap']\n .forEach(function(name) {\n var val = paramInfo[name];\n if (val != null) {\n // Convert string to enum\n if (typeof val === 'string') {\n val = Texture[val];\n }\n param[name] = val;\n }\n });\n\n var sizeScale = paramInfo.scale || 1;\n ['width', 'height']\n .forEach(function(name) {\n if (paramInfo[name] != null) {\n var val = paramInfo[name];\n if (typeof val === 'string') {\n val = val.trim();\n param[name] = createSizeParser(\n name, tryConvertExpr(val), sizeScale\n );\n }\n else {\n param[name] = val;\n }\n }\n });\n if (!param.width) {\n param.width = defaultWidthFunc;\n }\n if (!param.height) {\n param.height = defaultHeightFunc;\n }\n\n if (paramInfo.useMipmap != null) {\n param.useMipmap = paramInfo.useMipmap;\n }\n return param;\n}\n\nfunction loadTextures(json, lib, opts, callback) {\n if (!json.textures) {\n callback({});\n return;\n }\n var textures = {};\n var loading = 0;\n\n var cbd = false;\n var textureRootPath = opts.textureRootPath;\n util.each(json.textures, function(textureInfo, name) {\n var texture;\n var path = textureInfo.path;\n var parameters = convertParameter(textureInfo.parameters);\n if (Array.isArray(path) && path.length === 6) {\n if (textureRootPath) {\n path = path.map(function(item) {\n return util.relative2absolute(item, textureRootPath);\n });\n }\n texture = new TextureCube(parameters);\n }\n else if(typeof path === 'string') {\n if (textureRootPath) {\n path = util.relative2absolute(path, textureRootPath);\n }\n texture = new Texture2D(parameters);\n }\n else {\n return;\n }\n\n texture.load(path);\n loading++;\n texture.once('success', function() {\n textures[name] = texture;\n loading--;\n if (loading === 0) {\n callback(textures);\n cbd = true;\n }\n });\n });\n\n if (loading === 0 && !cbd) {\n callback(textures);\n }\n}\n\nfunction createSizeSetHandler(name, exprFunc) {\n return function (renderer) {\n // PENDING viewport size or window size\n var dpr = renderer.getDevicePixelRatio();\n // PENDING If multiply dpr ?\n var width = renderer.getWidth();\n var height = renderer.getHeight();\n var result = exprFunc(width, height, dpr);\n this.setParameter(name, result);\n };\n}\n\nfunction createSizeParser(name, exprFunc, scale) {\n scale = scale || 1;\n return function (renderer) {\n var dpr = renderer.getDevicePixelRatio();\n var width = renderer.getWidth() * scale;\n var height = renderer.getHeight() * scale;\n return exprFunc(width, height, dpr);\n };\n}\n\nfunction tryConvertExpr(string) {\n // PENDING\n var exprRes = /^expr\\((.*)\\)$/.exec(string);\n if (exprRes) {\n try {\n var func = new Function('width', 'height', 'dpr', 'return ' + exprRes[1]);\n // Try run t\n func(1, 1);\n\n return func;\n }\n catch (e) {\n throw new Error('Invalid expression.');\n }\n }\n}\n\nexport default createCompositor;\n","// DEPRECATED\nimport createCompositor from '../createCompositor';\nexport default createCompositor;","// Generate halton sequence\n// https://en.wikipedia.org/wiki/Halton_sequence\nfunction halton(index, base) {\n var result = 0;\n var f = 1 / base;\n var i = index;\n\n while (i > 0) {\n result = result + f * (i % base);\n i = Math.floor(i / base);\n f = f / base;\n }\n\n return result;\n}\n\nexport default halton;","export default \"@export ecgl.ssao.estimate\\n\\nuniform sampler2D depthTex;\\n\\nuniform sampler2D normalTex;\\n\\nuniform sampler2D noiseTex;\\n\\nuniform vec2 depthTexSize;\\n\\nuniform vec2 noiseTexSize;\\n\\nuniform mat4 projection;\\n\\nuniform mat4 projectionInv;\\n\\nuniform mat4 viewInverseTranspose;\\n\\nuniform vec3 kernel[KERNEL_SIZE];\\n\\nuniform float radius : 1;\\n\\nuniform float power : 1;\\n\\nuniform float bias: 1e-2;\\n\\nuniform float intensity: 1.0;\\n\\nvarying vec2 v_Texcoord;\\n\\nfloat ssaoEstimator(in vec3 originPos, in mat3 kernelBasis) {\\n float occlusion = 0.0;\\n\\n for (int i = 0; i < KERNEL_SIZE; i++) {\\n vec3 samplePos = kernel[i];\\n#ifdef NORMALTEX_ENABLED\\n samplePos = kernelBasis * samplePos;\\n#endif\\n samplePos = samplePos * radius + originPos;\\n\\n vec4 texCoord = projection * vec4(samplePos, 1.0);\\n texCoord.xy /= texCoord.w;\\n\\n vec4 depthTexel = texture2D(depthTex, texCoord.xy * 0.5 + 0.5);\\n\\n float sampleDepth = depthTexel.r * 2.0 - 1.0;\\n if (projection[3][3] == 0.0) {\\n sampleDepth = projection[3][2] / (sampleDepth * projection[2][3] - projection[2][2]);\\n }\\n else {\\n sampleDepth = (sampleDepth - projection[3][2]) / projection[2][2];\\n }\\n \\n float rangeCheck = smoothstep(0.0, 1.0, radius / abs(originPos.z - sampleDepth));\\n occlusion += rangeCheck * step(samplePos.z, sampleDepth - bias);\\n }\\n#ifdef NORMALTEX_ENABLED\\n occlusion = 1.0 - occlusion / float(KERNEL_SIZE);\\n#else\\n occlusion = 1.0 - clamp((occlusion / float(KERNEL_SIZE) - 0.6) * 2.5, 0.0, 1.0);\\n#endif\\n return pow(occlusion, power);\\n}\\n\\nvoid main()\\n{\\n\\n vec4 depthTexel = texture2D(depthTex, v_Texcoord);\\n\\n#ifdef NORMALTEX_ENABLED\\n vec4 tex = texture2D(normalTex, v_Texcoord);\\n if (dot(tex.rgb, tex.rgb) == 0.0) {\\n gl_FragColor = vec4(1.0);\\n return;\\n }\\n vec3 N = tex.rgb * 2.0 - 1.0;\\n N = (viewInverseTranspose * vec4(N, 0.0)).xyz;\\n\\n vec2 noiseTexCoord = depthTexSize / vec2(noiseTexSize) * v_Texcoord;\\n vec3 rvec = texture2D(noiseTex, noiseTexCoord).rgb * 2.0 - 1.0;\\n vec3 T = normalize(rvec - N * dot(rvec, N));\\n vec3 BT = normalize(cross(N, T));\\n mat3 kernelBasis = mat3(T, BT, N);\\n#else\\n if (depthTexel.r > 0.99999) {\\n gl_FragColor = vec4(1.0);\\n return;\\n }\\n mat3 kernelBasis;\\n#endif\\n\\n float z = depthTexel.r * 2.0 - 1.0;\\n\\n vec4 projectedPos = vec4(v_Texcoord * 2.0 - 1.0, z, 1.0);\\n vec4 p4 = projectionInv * projectedPos;\\n\\n vec3 position = p4.xyz / p4.w;\\n\\n float ao = ssaoEstimator(position, kernelBasis);\\n ao = clamp(1.0 - (1.0 - ao) * intensity, 0.0, 1.0);\\n gl_FragColor = vec4(vec3(ao), 1.0);\\n}\\n\\n@end\\n\\n\\n@export ecgl.ssao.blur\\n#define SHADER_NAME SSAO_BLUR\\n\\nuniform sampler2D ssaoTexture;\\n\\n#ifdef NORMALTEX_ENABLED\\nuniform sampler2D normalTex;\\n#endif\\n\\nvarying vec2 v_Texcoord;\\n\\nuniform vec2 textureSize;\\nuniform float blurSize : 1.0;\\n\\nuniform int direction: 0.0;\\n\\n#ifdef DEPTHTEX_ENABLED\\nuniform sampler2D depthTex;\\nuniform mat4 projection;\\nuniform float depthRange : 0.5;\\n\\nfloat getLinearDepth(vec2 coord)\\n{\\n float depth = texture2D(depthTex, coord).r * 2.0 - 1.0;\\n return projection[3][2] / (depth * projection[2][3] - projection[2][2]);\\n}\\n#endif\\n\\nvoid main()\\n{\\n float kernel[5];\\n kernel[0] = 0.122581;\\n kernel[1] = 0.233062;\\n kernel[2] = 0.288713;\\n kernel[3] = 0.233062;\\n kernel[4] = 0.122581;\\n\\n vec2 off = vec2(0.0);\\n if (direction == 0) {\\n off[0] = blurSize / textureSize.x;\\n }\\n else {\\n off[1] = blurSize / textureSize.y;\\n }\\n\\n vec2 coord = v_Texcoord;\\n\\n float sum = 0.0;\\n float weightAll = 0.0;\\n\\n#ifdef NORMALTEX_ENABLED\\n vec3 centerNormal = texture2D(normalTex, v_Texcoord).rgb * 2.0 - 1.0;\\n#endif\\n#if defined(DEPTHTEX_ENABLED)\\n float centerDepth = getLinearDepth(v_Texcoord);\\n#endif\\n\\n for (int i = 0; i < 5; i++) {\\n vec2 coord = clamp(v_Texcoord + vec2(float(i) - 2.0) * off, vec2(0.0), vec2(1.0));\\n\\n float w = kernel[i];\\n#ifdef NORMALTEX_ENABLED\\n vec3 normal = texture2D(normalTex, coord).rgb * 2.0 - 1.0;\\n w *= clamp(dot(normal, centerNormal), 0.0, 1.0);\\n#endif\\n#ifdef DEPTHTEX_ENABLED\\n float d = getLinearDepth(coord);\\n w *= (1.0 - smoothstep(abs(centerDepth - d) / depthRange, 0.0, 1.0));\\n#endif\\n\\n weightAll += w;\\n sum += texture2D(ssaoTexture, coord).r * w;\\n }\\n\\n gl_FragColor = vec4(vec3(sum / weightAll), 1.0);\\n}\\n\\n@end\\n\";","import Matrix4 from 'claygl/src/math/Matrix4';\nimport Vector3 from 'claygl/src/math/Vector3';\nimport Texture2D from 'claygl/src/Texture2D';\nimport Texture from 'claygl/src/Texture';\nimport Pass from 'claygl/src/compositor/Pass';\nimport Shader from 'claygl/src/Shader';\nimport FrameBuffer from 'claygl/src/FrameBuffer';\nimport halton from './halton';\nimport SSAOGLSL from './SSAO.glsl.js';\nShader.import(SSAOGLSL);\n\nfunction generateNoiseData(size) {\n var data = new Uint8Array(size * size * 4);\n var n = 0;\n var v3 = new Vector3();\n\n for (var i = 0; i < size; i++) {\n for (var j = 0; j < size; j++) {\n v3.set(Math.random() * 2 - 1, Math.random() * 2 - 1, 0).normalize();\n data[n++] = (v3.x * 0.5 + 0.5) * 255;\n data[n++] = (v3.y * 0.5 + 0.5) * 255;\n data[n++] = 0;\n data[n++] = 255;\n }\n }\n\n return data;\n}\n\nfunction generateNoiseTexture(size) {\n return new Texture2D({\n pixels: generateNoiseData(size),\n wrapS: Texture.REPEAT,\n wrapT: Texture.REPEAT,\n width: size,\n height: size\n });\n}\n\nfunction generateKernel(size, offset, hemisphere) {\n var kernel = new Float32Array(size * 3);\n offset = offset || 0;\n\n for (var i = 0; i < size; i++) {\n var phi = halton(i + offset, 2) * (hemisphere ? 1 : 2) * Math.PI;\n var theta = halton(i + offset, 3) * Math.PI;\n var r = Math.random();\n var x = Math.cos(phi) * Math.sin(theta) * r;\n var y = Math.cos(theta) * r;\n var z = Math.sin(phi) * Math.sin(theta) * r;\n kernel[i * 3] = x;\n kernel[i * 3 + 1] = y;\n kernel[i * 3 + 2] = z;\n }\n\n return kernel; // var kernel = new Float32Array(size * 3);\n // var v3 = new Vector3();\n // for (var i = 0; i < size; i++) {\n // v3.set(Math.random() * 2 - 1, Math.random() * 2 - 1, Math.random())\n // .normalize().scale(Math.random());\n // kernel[i * 3] = v3.x;\n // kernel[i * 3 + 1] = v3.y;\n // kernel[i * 3 + 2] = v3.z;\n // }\n // return kernel;\n}\n\nfunction SSAOPass(opt) {\n opt = opt || {};\n this._ssaoPass = new Pass({\n fragment: Shader.source('ecgl.ssao.estimate')\n });\n this._blurPass = new Pass({\n fragment: Shader.source('ecgl.ssao.blur')\n });\n this._framebuffer = new FrameBuffer({\n depthBuffer: false\n });\n this._ssaoTexture = new Texture2D();\n this._blurTexture = new Texture2D();\n this._blurTexture2 = new Texture2D();\n this._depthTex = opt.depthTexture;\n this._normalTex = opt.normalTexture;\n this.setNoiseSize(4);\n this.setKernelSize(opt.kernelSize || 12);\n\n if (opt.radius != null) {\n this.setParameter('radius', opt.radius);\n }\n\n if (opt.power != null) {\n this.setParameter('power', opt.power);\n }\n\n if (!this._normalTex) {\n this._ssaoPass.material.disableTexture('normalTex');\n\n this._blurPass.material.disableTexture('normalTex');\n }\n\n if (!this._depthTex) {\n this._blurPass.material.disableTexture('depthTex');\n }\n\n this._blurPass.material.setUniform('normalTex', this._normalTex);\n\n this._blurPass.material.setUniform('depthTex', this._depthTex);\n}\n\nSSAOPass.prototype.setDepthTexture = function (depthTex) {\n this._depthTex = depthTex;\n};\n\nSSAOPass.prototype.setNormalTexture = function (normalTex) {\n this._normalTex = normalTex;\n\n this._ssaoPass.material[normalTex ? 'enableTexture' : 'disableTexture']('normalTex'); // Switch between hemisphere and shere kernel.\n\n\n this.setKernelSize(this._kernelSize);\n};\n\nSSAOPass.prototype.update = function (renderer, camera, frame) {\n var width = renderer.getWidth();\n var height = renderer.getHeight();\n var ssaoPass = this._ssaoPass;\n var blurPass = this._blurPass;\n ssaoPass.setUniform('kernel', this._kernels[frame % this._kernels.length]);\n ssaoPass.setUniform('depthTex', this._depthTex);\n\n if (this._normalTex != null) {\n ssaoPass.setUniform('normalTex', this._normalTex);\n }\n\n ssaoPass.setUniform('depthTexSize', [this._depthTex.width, this._depthTex.height]);\n var viewInverseTranspose = new Matrix4();\n Matrix4.transpose(viewInverseTranspose, camera.worldTransform);\n ssaoPass.setUniform('projection', camera.projectionMatrix.array);\n ssaoPass.setUniform('projectionInv', camera.invProjectionMatrix.array);\n ssaoPass.setUniform('viewInverseTranspose', viewInverseTranspose.array);\n var ssaoTexture = this._ssaoTexture;\n var blurTexture = this._blurTexture;\n var blurTexture2 = this._blurTexture2;\n ssaoTexture.width = width / 2;\n ssaoTexture.height = height / 2;\n blurTexture.width = width;\n blurTexture.height = height;\n blurTexture2.width = width;\n blurTexture2.height = height;\n\n this._framebuffer.attach(ssaoTexture);\n\n this._framebuffer.bind(renderer);\n\n renderer.gl.clearColor(1, 1, 1, 1);\n renderer.gl.clear(renderer.gl.COLOR_BUFFER_BIT);\n ssaoPass.render(renderer);\n blurPass.setUniform('textureSize', [width / 2, height / 2]);\n blurPass.setUniform('projection', camera.projectionMatrix.array);\n\n this._framebuffer.attach(blurTexture);\n\n blurPass.setUniform('direction', 0);\n blurPass.setUniform('ssaoTexture', ssaoTexture);\n blurPass.render(renderer);\n\n this._framebuffer.attach(blurTexture2);\n\n blurPass.setUniform('textureSize', [width, height]);\n blurPass.setUniform('direction', 1);\n blurPass.setUniform('ssaoTexture', blurTexture);\n blurPass.render(renderer);\n\n this._framebuffer.unbind(renderer); // Restore clear\n\n\n var clearColor = renderer.clearColor;\n renderer.gl.clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);\n};\n\nSSAOPass.prototype.getTargetTexture = function () {\n return this._blurTexture2;\n};\n\nSSAOPass.prototype.setParameter = function (name, val) {\n if (name === 'noiseTexSize') {\n this.setNoiseSize(val);\n } else if (name === 'kernelSize') {\n this.setKernelSize(val);\n } else if (name === 'intensity') {\n this._ssaoPass.material.set('intensity', val);\n } else {\n this._ssaoPass.setUniform(name, val);\n }\n};\n\nSSAOPass.prototype.setKernelSize = function (size) {\n this._kernelSize = size;\n\n this._ssaoPass.material.define('fragment', 'KERNEL_SIZE', size);\n\n this._kernels = this._kernels || [];\n\n for (var i = 0; i < 30; i++) {\n this._kernels[i] = generateKernel(size, i * size, !!this._normalTex);\n }\n};\n\nSSAOPass.prototype.setNoiseSize = function (size) {\n var texture = this._ssaoPass.getUniform('noiseTex');\n\n if (!texture) {\n texture = generateNoiseTexture(size);\n\n this._ssaoPass.setUniform('noiseTex', generateNoiseTexture(size));\n } else {\n texture.data = generateNoiseData(size);\n texture.width = texture.height = size;\n texture.dirty();\n }\n\n this._ssaoPass.setUniform('noiseTexSize', [size, size]);\n};\n\nSSAOPass.prototype.dispose = function (renderer) {\n this._blurTexture.dispose(renderer);\n\n this._ssaoTexture.dispose(renderer);\n\n this._blurTexture2.dispose(renderer);\n};\n\nexport default SSAOPass;","export default \"@export ecgl.ssr.main\\n\\n#define SHADER_NAME SSR\\n#define MAX_ITERATION 20;\\n#define SAMPLE_PER_FRAME 5;\\n#define TOTAL_SAMPLES 128;\\n\\nuniform sampler2D sourceTexture;\\nuniform sampler2D gBufferTexture1;\\nuniform sampler2D gBufferTexture2;\\nuniform sampler2D gBufferTexture3;\\nuniform samplerCube specularCubemap;\\nuniform float specularIntensity: 1;\\n\\nuniform mat4 projection;\\nuniform mat4 projectionInv;\\nuniform mat4 toViewSpace;\\nuniform mat4 toWorldSpace;\\n\\nuniform float maxRayDistance: 200;\\n\\nuniform float pixelStride: 16;\\nuniform float pixelStrideZCutoff: 50; \\nuniform float screenEdgeFadeStart: 0.9; \\nuniform float eyeFadeStart : 0.2; uniform float eyeFadeEnd: 0.8; \\nuniform float minGlossiness: 0.2; uniform float zThicknessThreshold: 1;\\n\\nuniform float nearZ;\\nuniform vec2 viewportSize : VIEWPORT_SIZE;\\n\\nuniform float jitterOffset: 0;\\n\\nvarying vec2 v_Texcoord;\\n\\n#ifdef DEPTH_DECODE\\n@import clay.util.decode_float\\n#endif\\n\\n#ifdef PHYSICALLY_CORRECT\\nuniform sampler2D normalDistribution;\\nuniform float sampleOffset: 0;\\nuniform vec2 normalDistributionSize;\\n\\nvec3 transformNormal(vec3 H, vec3 N) {\\n vec3 upVector = N.y > 0.999 ? vec3(1.0, 0.0, 0.0) : vec3(0.0, 1.0, 0.0);\\n vec3 tangentX = normalize(cross(N, upVector));\\n vec3 tangentZ = cross(N, tangentX);\\n return normalize(tangentX * H.x + N * H.y + tangentZ * H.z);\\n}\\nvec3 importanceSampleNormalGGX(float i, float roughness, vec3 N) {\\n float p = fract((i + sampleOffset) / float(TOTAL_SAMPLES));\\n vec3 H = texture2D(normalDistribution,vec2(roughness, p)).rgb;\\n return transformNormal(H, N);\\n}\\nfloat G_Smith(float g, float ndv, float ndl) {\\n float roughness = 1.0 - g;\\n float k = roughness * roughness / 2.0;\\n float G1V = ndv / (ndv * (1.0 - k) + k);\\n float G1L = ndl / (ndl * (1.0 - k) + k);\\n return G1L * G1V;\\n}\\nvec3 F_Schlick(float ndv, vec3 spec) {\\n return spec + (1.0 - spec) * pow(1.0 - ndv, 5.0);\\n}\\n#endif\\n\\nfloat fetchDepth(sampler2D depthTexture, vec2 uv)\\n{\\n vec4 depthTexel = texture2D(depthTexture, uv);\\n return depthTexel.r * 2.0 - 1.0;\\n}\\n\\nfloat linearDepth(float depth)\\n{\\n if (projection[3][3] == 0.0) {\\n return projection[3][2] / (depth * projection[2][3] - projection[2][2]);\\n }\\n else {\\n return (depth - projection[3][2]) / projection[2][2];\\n }\\n}\\n\\nbool rayIntersectDepth(float rayZNear, float rayZFar, vec2 hitPixel)\\n{\\n if (rayZFar > rayZNear)\\n {\\n float t = rayZFar; rayZFar = rayZNear; rayZNear = t;\\n }\\n float cameraZ = linearDepth(fetchDepth(gBufferTexture2, hitPixel));\\n return rayZFar <= cameraZ && rayZNear >= cameraZ - zThicknessThreshold;\\n}\\n\\n\\nbool traceScreenSpaceRay(\\n vec3 rayOrigin, vec3 rayDir, float jitter,\\n out vec2 hitPixel, out vec3 hitPoint, out float iterationCount\\n)\\n{\\n float rayLength = ((rayOrigin.z + rayDir.z * maxRayDistance) > -nearZ)\\n ? (-nearZ - rayOrigin.z) / rayDir.z : maxRayDistance;\\n\\n vec3 rayEnd = rayOrigin + rayDir * rayLength;\\n\\n vec4 H0 = projection * vec4(rayOrigin, 1.0);\\n vec4 H1 = projection * vec4(rayEnd, 1.0);\\n\\n float k0 = 1.0 / H0.w, k1 = 1.0 / H1.w;\\n\\n vec3 Q0 = rayOrigin * k0, Q1 = rayEnd * k1;\\n\\n vec2 P0 = (H0.xy * k0 * 0.5 + 0.5) * viewportSize;\\n vec2 P1 = (H1.xy * k1 * 0.5 + 0.5) * viewportSize;\\n\\n P1 += dot(P1 - P0, P1 - P0) < 0.0001 ? 0.01 : 0.0;\\n vec2 delta = P1 - P0;\\n\\n bool permute = false;\\n if (abs(delta.x) < abs(delta.y)) {\\n permute = true;\\n delta = delta.yx;\\n P0 = P0.yx;\\n P1 = P1.yx;\\n }\\n float stepDir = sign(delta.x);\\n float invdx = stepDir / delta.x;\\n\\n vec3 dQ = (Q1 - Q0) * invdx;\\n float dk = (k1 - k0) * invdx;\\n\\n vec2 dP = vec2(stepDir, delta.y * invdx);\\n\\n float strideScaler = 1.0 - min(1.0, -rayOrigin.z / pixelStrideZCutoff);\\n float pixStride = 1.0 + strideScaler * pixelStride;\\n\\n dP *= pixStride; dQ *= pixStride; dk *= pixStride;\\n\\n vec4 pqk = vec4(P0, Q0.z, k0);\\n vec4 dPQK = vec4(dP, dQ.z, dk);\\n\\n pqk += dPQK * jitter;\\n float rayZFar = (dPQK.z * 0.5 + pqk.z) / (dPQK.w * 0.5 + pqk.w);\\n float rayZNear;\\n\\n bool intersect = false;\\n\\n vec2 texelSize = 1.0 / viewportSize;\\n\\n iterationCount = 0.0;\\n\\n for (int i = 0; i < MAX_ITERATION; i++)\\n {\\n pqk += dPQK;\\n\\n rayZNear = rayZFar;\\n rayZFar = (dPQK.z * 0.5 + pqk.z) / (dPQK.w * 0.5 + pqk.w);\\n\\n hitPixel = permute ? pqk.yx : pqk.xy;\\n hitPixel *= texelSize;\\n\\n intersect = rayIntersectDepth(rayZNear, rayZFar, hitPixel);\\n\\n iterationCount += 1.0;\\n\\n dPQK *= 1.2;\\n\\n if (intersect) {\\n break;\\n }\\n }\\n\\n Q0.xy += dQ.xy * iterationCount;\\n Q0.z = pqk.z;\\n hitPoint = Q0 / pqk.w;\\n\\n return intersect;\\n}\\n\\nfloat calculateAlpha(\\n float iterationCount, float reflectivity,\\n vec2 hitPixel, vec3 hitPoint, float dist, vec3 rayDir\\n)\\n{\\n float alpha = clamp(reflectivity, 0.0, 1.0);\\n alpha *= 1.0 - (iterationCount / float(MAX_ITERATION));\\n vec2 hitPixelNDC = hitPixel * 2.0 - 1.0;\\n float maxDimension = min(1.0, max(abs(hitPixelNDC.x), abs(hitPixelNDC.y)));\\n alpha *= 1.0 - max(0.0, maxDimension - screenEdgeFadeStart) / (1.0 - screenEdgeFadeStart);\\n\\n float _eyeFadeStart = eyeFadeStart;\\n float _eyeFadeEnd = eyeFadeEnd;\\n if (_eyeFadeStart > _eyeFadeEnd) {\\n float tmp = _eyeFadeEnd;\\n _eyeFadeEnd = _eyeFadeStart;\\n _eyeFadeStart = tmp;\\n }\\n\\n float eyeDir = clamp(rayDir.z, _eyeFadeStart, _eyeFadeEnd);\\n alpha *= 1.0 - (eyeDir - _eyeFadeStart) / (_eyeFadeEnd - _eyeFadeStart);\\n\\n alpha *= 1.0 - clamp(dist / maxRayDistance, 0.0, 1.0);\\n\\n return alpha;\\n}\\n\\n@import clay.util.rand\\n\\n@import clay.util.rgbm\\n\\nvoid main()\\n{\\n vec4 normalAndGloss = texture2D(gBufferTexture1, v_Texcoord);\\n\\n if (dot(normalAndGloss.rgb, vec3(1.0)) == 0.0) {\\n discard;\\n }\\n\\n float g = normalAndGloss.a;\\n#if !defined(PHYSICALLY_CORRECT)\\n if (g <= minGlossiness) {\\n discard;\\n }\\n#endif\\n\\n float reflectivity = (g - minGlossiness) / (1.0 - minGlossiness);\\n\\n vec3 N = normalize(normalAndGloss.rgb * 2.0 - 1.0);\\n N = normalize((toViewSpace * vec4(N, 0.0)).xyz);\\n\\n vec4 projectedPos = vec4(v_Texcoord * 2.0 - 1.0, fetchDepth(gBufferTexture2, v_Texcoord), 1.0);\\n vec4 pos = projectionInv * projectedPos;\\n vec3 rayOrigin = pos.xyz / pos.w;\\n vec3 V = -normalize(rayOrigin);\\n\\n float ndv = clamp(dot(N, V), 0.0, 1.0);\\n float iterationCount;\\n float jitter = rand(fract(v_Texcoord + jitterOffset));\\n\\n#ifdef PHYSICALLY_CORRECT\\n vec4 color = vec4(vec3(0.0), 1.0);\\n vec4 albedoMetalness = texture2D(gBufferTexture3, v_Texcoord);\\n vec3 albedo = albedoMetalness.rgb;\\n float m = albedoMetalness.a;\\n vec3 diffuseColor = albedo * (1.0 - m);\\n vec3 spec = mix(vec3(0.04), albedo, m);\\n\\n float jitter2 = rand(fract(v_Texcoord)) * float(TOTAL_SAMPLES);\\n\\n for (int i = 0; i < SAMPLE_PER_FRAME; i++) {\\n vec3 H = importanceSampleNormalGGX(float(i) + jitter2, 1.0 - g, N);\\n vec3 rayDir = normalize(reflect(-V, H));\\n#else\\n vec3 rayDir = normalize(reflect(-V, N));\\n#endif\\n vec2 hitPixel;\\n vec3 hitPoint;\\n\\n bool intersect = traceScreenSpaceRay(rayOrigin, rayDir, jitter, hitPixel, hitPoint, iterationCount);\\n\\n float dist = distance(rayOrigin, hitPoint);\\n\\n vec3 hitNormal = texture2D(gBufferTexture1, hitPixel).rgb * 2.0 - 1.0;\\n hitNormal = normalize((toViewSpace * vec4(hitNormal, 0.0)).xyz);\\n#ifdef PHYSICALLY_CORRECT\\n float ndl = clamp(dot(N, rayDir), 0.0, 1.0);\\n float vdh = clamp(dot(V, H), 0.0, 1.0);\\n float ndh = clamp(dot(N, H), 0.0, 1.0);\\n vec3 litTexel = vec3(0.0);\\n if (dot(hitNormal, rayDir) < 0.0 && intersect) {\\n litTexel = texture2D(sourceTexture, hitPixel).rgb;\\n litTexel *= pow(clamp(1.0 - dist / 200.0, 0.0, 1.0), 3.0);\\n\\n }\\n else {\\n #ifdef SPECULARCUBEMAP_ENABLED\\n vec3 rayDirW = normalize(toWorldSpace * vec4(rayDir, 0.0)).rgb;\\n litTexel = RGBMDecode(textureCubeLodEXT(specularCubemap, rayDirW, 0.0), 8.12).rgb * specularIntensity;\\n#endif\\n }\\n color.rgb += ndl * litTexel * (\\n F_Schlick(ndl, spec) * G_Smith(g, ndv, ndl) * vdh / (ndh * ndv + 0.001)\\n );\\n }\\n color.rgb /= float(SAMPLE_PER_FRAME);\\n#else\\n #if !defined(SPECULARCUBEMAP_ENABLED)\\n if (dot(hitNormal, rayDir) >= 0.0) {\\n discard;\\n }\\n if (!intersect) {\\n discard;\\n }\\n#endif\\n float alpha = clamp(calculateAlpha(iterationCount, reflectivity, hitPixel, hitPoint, dist, rayDir), 0.0, 1.0);\\n vec4 color = texture2D(sourceTexture, hitPixel);\\n color.rgb *= alpha;\\n\\n#ifdef SPECULARCUBEMAP_ENABLED\\n vec3 rayDirW = normalize(toWorldSpace * vec4(rayDir, 0.0)).rgb;\\n alpha = alpha * (intersect ? 1.0 : 0.0);\\n float bias = (1.0 -g) * 5.0;\\n color.rgb += (1.0 - alpha)\\n * RGBMDecode(textureCubeLodEXT(specularCubemap, rayDirW, bias), 8.12).rgb\\n * specularIntensity;\\n#endif\\n\\n#endif\\n\\n gl_FragColor = encodeHDR(color);\\n}\\n@end\\n\\n@export ecgl.ssr.blur\\n\\nuniform sampler2D texture;\\nuniform sampler2D gBufferTexture1;\\nuniform sampler2D gBufferTexture2;\\nuniform mat4 projection;\\nuniform float depthRange : 0.05;\\n\\nvarying vec2 v_Texcoord;\\n\\nuniform vec2 textureSize;\\nuniform float blurSize : 1.0;\\n\\n#ifdef BLEND\\n #ifdef SSAOTEX_ENABLED\\nuniform sampler2D ssaoTex;\\n #endif\\nuniform sampler2D sourceTexture;\\n#endif\\n\\nfloat getLinearDepth(vec2 coord)\\n{\\n float depth = texture2D(gBufferTexture2, coord).r * 2.0 - 1.0;\\n return projection[3][2] / (depth * projection[2][3] - projection[2][2]);\\n}\\n\\n@import clay.util.rgbm\\n\\n\\nvoid main()\\n{\\n @import clay.compositor.kernel.gaussian_9\\n\\n vec4 centerNTexel = texture2D(gBufferTexture1, v_Texcoord);\\n float g = centerNTexel.a;\\n float maxBlurSize = clamp(1.0 - g, 0.0, 1.0) * blurSize;\\n#ifdef VERTICAL\\n vec2 off = vec2(0.0, maxBlurSize / textureSize.y);\\n#else\\n vec2 off = vec2(maxBlurSize / textureSize.x, 0.0);\\n#endif\\n\\n vec2 coord = v_Texcoord;\\n\\n vec4 sum = vec4(0.0);\\n float weightAll = 0.0;\\n\\n vec3 cN = centerNTexel.rgb * 2.0 - 1.0;\\n float cD = getLinearDepth(v_Texcoord);\\n for (int i = 0; i < 9; i++) {\\n vec2 coord = clamp((float(i) - 4.0) * off + v_Texcoord, vec2(0.0), vec2(1.0));\\n float w = gaussianKernel[i]\\n * clamp(dot(cN, texture2D(gBufferTexture1, coord).rgb * 2.0 - 1.0), 0.0, 1.0);\\n float d = getLinearDepth(coord);\\n w *= (1.0 - smoothstep(abs(cD - d) / depthRange, 0.0, 1.0));\\n\\n weightAll += w;\\n sum += decodeHDR(texture2D(texture, coord)) * w;\\n }\\n\\n#ifdef BLEND\\n float aoFactor = 1.0;\\n #ifdef SSAOTEX_ENABLED\\n aoFactor = texture2D(ssaoTex, v_Texcoord).r;\\n #endif\\n gl_FragColor = encodeHDR(\\n sum / weightAll * aoFactor + decodeHDR(texture2D(sourceTexture, v_Texcoord))\\n );\\n#else\\n gl_FragColor = encodeHDR(sum / weightAll);\\n#endif\\n}\\n\\n@end\";","import Matrix4 from 'claygl/src/math/Matrix4';\nimport Vector3 from 'claygl/src/math/Vector3';\nimport Texture2D from 'claygl/src/Texture2D';\nimport Texture from 'claygl/src/Texture';\nimport Pass from 'claygl/src/compositor/Pass';\nimport Shader from 'claygl/src/Shader';\nimport FrameBuffer from 'claygl/src/FrameBuffer';\nimport halton from './halton';\nimport cubemapUtil from 'claygl/src/util/cubemap';\nimport SSRGLSLCode from './SSR.glsl.js';\nShader.import(SSRGLSLCode);\n\nfunction SSRPass(opt) {\n opt = opt || {};\n this._ssrPass = new Pass({\n fragment: Shader.source('ecgl.ssr.main'),\n clearColor: [0, 0, 0, 0]\n });\n this._blurPass1 = new Pass({\n fragment: Shader.source('ecgl.ssr.blur'),\n clearColor: [0, 0, 0, 0]\n });\n this._blurPass2 = new Pass({\n fragment: Shader.source('ecgl.ssr.blur'),\n clearColor: [0, 0, 0, 0]\n });\n this._blendPass = new Pass({\n fragment: Shader.source('clay.compositor.blend')\n });\n\n this._blendPass.material.disableTexturesAll();\n\n this._blendPass.material.enableTexture(['texture1', 'texture2']);\n\n this._ssrPass.setUniform('gBufferTexture1', opt.normalTexture);\n\n this._ssrPass.setUniform('gBufferTexture2', opt.depthTexture); // this._ssrPass.setUniform('gBufferTexture3', opt.albedoTexture);\n\n\n this._blurPass1.setUniform('gBufferTexture1', opt.normalTexture);\n\n this._blurPass1.setUniform('gBufferTexture2', opt.depthTexture);\n\n this._blurPass2.setUniform('gBufferTexture1', opt.normalTexture);\n\n this._blurPass2.setUniform('gBufferTexture2', opt.depthTexture);\n\n this._blurPass2.material.define('fragment', 'VERTICAL');\n\n this._blurPass2.material.define('fragment', 'BLEND');\n\n this._ssrTexture = new Texture2D({\n type: Texture.HALF_FLOAT\n });\n this._texture2 = new Texture2D({\n type: Texture.HALF_FLOAT\n });\n this._texture3 = new Texture2D({\n type: Texture.HALF_FLOAT\n });\n this._prevTexture = new Texture2D({\n type: Texture.HALF_FLOAT\n });\n this._currentTexture = new Texture2D({\n type: Texture.HALF_FLOAT\n });\n this._frameBuffer = new FrameBuffer({\n depthBuffer: false\n });\n this._normalDistribution = null;\n this._totalSamples = 256;\n this._samplePerFrame = 4;\n\n this._ssrPass.material.define('fragment', 'SAMPLE_PER_FRAME', this._samplePerFrame);\n\n this._ssrPass.material.define('fragment', 'TOTAL_SAMPLES', this._totalSamples);\n\n this._downScale = 1;\n}\n\nSSRPass.prototype.setAmbientCubemap = function (specularCubemap, specularIntensity) {\n this._ssrPass.material.set('specularCubemap', specularCubemap);\n\n this._ssrPass.material.set('specularIntensity', specularIntensity);\n\n var enableSpecularMap = specularCubemap && specularIntensity;\n\n this._ssrPass.material[enableSpecularMap ? 'enableTexture' : 'disableTexture']('specularCubemap');\n};\n\nSSRPass.prototype.update = function (renderer, camera, sourceTexture, frame) {\n var width = renderer.getWidth();\n var height = renderer.getHeight();\n var ssrTexture = this._ssrTexture;\n var texture2 = this._texture2;\n var texture3 = this._texture3;\n ssrTexture.width = this._prevTexture.width = this._currentTexture.width = width / this._downScale;\n ssrTexture.height = this._prevTexture.height = this._currentTexture.height = height / this._downScale;\n texture2.width = texture3.width = width;\n texture2.height = texture3.height = height;\n var frameBuffer = this._frameBuffer;\n var ssrPass = this._ssrPass;\n var blurPass1 = this._blurPass1;\n var blurPass2 = this._blurPass2;\n var blendPass = this._blendPass;\n var toViewSpace = new Matrix4();\n var toWorldSpace = new Matrix4();\n Matrix4.transpose(toViewSpace, camera.worldTransform);\n Matrix4.transpose(toWorldSpace, camera.viewMatrix);\n ssrPass.setUniform('sourceTexture', sourceTexture);\n ssrPass.setUniform('projection', camera.projectionMatrix.array);\n ssrPass.setUniform('projectionInv', camera.invProjectionMatrix.array);\n ssrPass.setUniform('toViewSpace', toViewSpace.array);\n ssrPass.setUniform('toWorldSpace', toWorldSpace.array);\n ssrPass.setUniform('nearZ', camera.near);\n var percent = frame / this._totalSamples * this._samplePerFrame;\n ssrPass.setUniform('jitterOffset', percent);\n ssrPass.setUniform('sampleOffset', frame * this._samplePerFrame);\n blurPass1.setUniform('textureSize', [ssrTexture.width, ssrTexture.height]);\n blurPass2.setUniform('textureSize', [width, height]);\n blurPass2.setUniform('sourceTexture', sourceTexture);\n blurPass1.setUniform('projection', camera.projectionMatrix.array);\n blurPass2.setUniform('projection', camera.projectionMatrix.array);\n frameBuffer.attach(ssrTexture);\n frameBuffer.bind(renderer);\n ssrPass.render(renderer);\n\n if (this._physicallyCorrect) {\n frameBuffer.attach(this._currentTexture);\n blendPass.setUniform('texture1', this._prevTexture);\n blendPass.setUniform('texture2', ssrTexture);\n blendPass.material.set({\n 'weight1': frame >= 1 ? 0.95 : 0,\n 'weight2': frame >= 1 ? 0.05 : 1 // weight1: frame >= 1 ? 1 : 0,\n // weight2: 1\n\n });\n blendPass.render(renderer);\n }\n\n frameBuffer.attach(texture2);\n blurPass1.setUniform('texture', this._physicallyCorrect ? this._currentTexture : ssrTexture);\n blurPass1.render(renderer);\n frameBuffer.attach(texture3);\n blurPass2.setUniform('texture', texture2);\n blurPass2.render(renderer);\n frameBuffer.unbind(renderer);\n\n if (this._physicallyCorrect) {\n var tmp = this._prevTexture;\n this._prevTexture = this._currentTexture;\n this._currentTexture = tmp;\n }\n};\n\nSSRPass.prototype.getTargetTexture = function () {\n return this._texture3;\n};\n\nSSRPass.prototype.setParameter = function (name, val) {\n if (name === 'maxIteration') {\n this._ssrPass.material.define('fragment', 'MAX_ITERATION', val);\n } else {\n this._ssrPass.setUniform(name, val);\n }\n};\n\nSSRPass.prototype.setPhysicallyCorrect = function (isPhysicallyCorrect) {\n if (isPhysicallyCorrect) {\n if (!this._normalDistribution) {\n this._normalDistribution = cubemapUtil.generateNormalDistribution(64, this._totalSamples);\n }\n\n this._ssrPass.material.define('fragment', 'PHYSICALLY_CORRECT');\n\n this._ssrPass.material.set('normalDistribution', this._normalDistribution);\n\n this._ssrPass.material.set('normalDistributionSize', [64, this._totalSamples]);\n } else {\n this._ssrPass.material.undefine('fragment', 'PHYSICALLY_CORRECT');\n }\n\n this._physicallyCorrect = isPhysicallyCorrect;\n};\n\nSSRPass.prototype.setSSAOTexture = function (texture) {\n var blendPass = this._blurPass2;\n\n if (texture) {\n blendPass.material.enableTexture('ssaoTex');\n blendPass.material.set('ssaoTex', texture);\n } else {\n blendPass.material.disableTexture('ssaoTex');\n }\n};\n\nSSRPass.prototype.isFinished = function (frame) {\n if (this._physicallyCorrect) {\n return frame > this._totalSamples / this._samplePerFrame;\n } else {\n return true;\n }\n};\n\nSSRPass.prototype.dispose = function (renderer) {\n this._ssrTexture.dispose(renderer);\n\n this._texture2.dispose(renderer);\n\n this._texture3.dispose(renderer);\n\n this._prevTexture.dispose(renderer);\n\n this._currentTexture.dispose(renderer);\n\n this._frameBuffer.dispose(renderer);\n};\n\nexport default SSRPass;","// Based on https://bl.ocks.org/mbostock/19168c663618b707158\nexport default [0.0, 0.0, -0.321585265978, -0.154972575841, 0.458126042375, 0.188473391593, 0.842080129861, 0.527766490688, 0.147304551086, -0.659453822776, -0.331943915203, -0.940619700594, 0.0479226680259, 0.54812163202, 0.701581552186, -0.709825561388, -0.295436780218, 0.940589268233, -0.901489676764, 0.237713156085, 0.973570876096, -0.109899459384, -0.866792314779, -0.451805525005, 0.330975007087, 0.800048655954, -0.344275183665, 0.381779221166, -0.386139432542, -0.437418421534, -0.576478634965, -0.0148463392551, 0.385798197415, -0.262426961053, -0.666302061145, 0.682427250835, -0.628010632582, -0.732836215494, 0.10163141741, -0.987658134403, 0.711995289051, -0.320024291314, 0.0296005138058, 0.950296523438, 0.0130612307608, -0.351024443122, -0.879596633704, -0.10478487883, 0.435712737232, 0.504254490347, 0.779203817497, 0.206477676721, 0.388264289969, -0.896736162545, -0.153106280781, -0.629203242522, -0.245517550697, 0.657969239148, 0.126830499058, 0.26862328493, -0.634888119007, -0.302301223431, 0.617074219636, 0.779817204925];","export default \"@export ecgl.normal.vertex\\n\\n@import ecgl.common.transformUniforms\\n\\n@import ecgl.common.uv.header\\n\\n@import ecgl.common.attributes\\n\\nvarying vec3 v_Normal;\\nvarying vec3 v_WorldPosition;\\n\\n@import ecgl.common.normalMap.vertexHeader\\n\\n@import ecgl.common.vertexAnimation.header\\n\\nvoid main()\\n{\\n\\n @import ecgl.common.vertexAnimation.main\\n\\n @import ecgl.common.uv.main\\n\\n v_Normal = normalize((worldInverseTranspose * vec4(normal, 0.0)).xyz);\\n v_WorldPosition = (world * vec4(pos, 1.0)).xyz;\\n\\n @import ecgl.common.normalMap.vertexMain\\n\\n gl_Position = worldViewProjection * vec4(pos, 1.0);\\n\\n}\\n\\n\\n@end\\n\\n\\n@export ecgl.normal.fragment\\n\\n#define ROUGHNESS_CHANEL 0\\n\\nuniform bool useBumpMap;\\nuniform bool useRoughnessMap;\\nuniform bool doubleSide;\\nuniform float roughness;\\n\\n@import ecgl.common.uv.fragmentHeader\\n\\nvarying vec3 v_Normal;\\nvarying vec3 v_WorldPosition;\\n\\nuniform mat4 viewInverse : VIEWINVERSE;\\n\\n@import ecgl.common.normalMap.fragmentHeader\\n@import ecgl.common.bumpMap.header\\n\\nuniform sampler2D roughnessMap;\\n\\nvoid main()\\n{\\n vec3 N = v_Normal;\\n \\n bool flipNormal = false;\\n if (doubleSide) {\\n vec3 eyePos = viewInverse[3].xyz;\\n vec3 V = normalize(eyePos - v_WorldPosition);\\n\\n if (dot(N, V) < 0.0) {\\n flipNormal = true;\\n }\\n }\\n\\n @import ecgl.common.normalMap.fragmentMain\\n\\n if (useBumpMap) {\\n N = bumpNormal(v_WorldPosition, v_Normal, N);\\n }\\n\\n float g = 1.0 - roughness;\\n\\n if (useRoughnessMap) {\\n float g2 = 1.0 - texture2D(roughnessMap, v_DetailTexcoord)[ROUGHNESS_CHANEL];\\n g = clamp(g2 + (g - 0.5) * 2.0, 0.0, 1.0);\\n }\\n\\n if (flipNormal) {\\n N = -N;\\n }\\n\\n gl_FragColor.rgb = (N.xyz + 1.0) * 0.5;\\n gl_FragColor.a = g;\\n}\\n@end\";","// NormalPass will generate normal and depth data.\n// TODO Animation\nimport Texture2D from 'claygl/src/Texture2D';\nimport Texture from 'claygl/src/Texture';\nimport Shader from 'claygl/src/Shader';\nimport FrameBuffer from 'claygl/src/FrameBuffer';\nimport Material from 'claygl/src/Material';\nimport Pass from 'claygl/src/compositor/Pass';\nimport textureUtil from 'claygl/src/util/texture';\nimport normalGLSL from '../util/shader/normal.glsl.js';\nShader.import(normalGLSL);\n\nfunction attachTextureToSlot(renderer, program, symbol, texture, slot) {\n var gl = renderer.gl;\n program.setUniform(gl, '1i', symbol, slot);\n gl.activeTexture(gl.TEXTURE0 + slot); // Maybe texture is not loaded yet;\n\n if (texture.isRenderable()) {\n texture.bind(renderer);\n } else {\n // Bind texture to null\n texture.unbind(renderer);\n }\n} // TODO Use globalShader insteadof globalMaterial?\n\n\nfunction getBeforeRenderHook(renderer, defaultNormalMap, defaultBumpMap, defaultRoughnessMap, normalMaterial) {\n var previousNormalMap;\n var previousBumpMap;\n var previousRoughnessMap;\n var previousRenderable;\n var gl = renderer.gl;\n return function (renderable, normalMaterial, prevNormalMaterial) {\n // Material not change\n if (previousRenderable && previousRenderable.material === renderable.material) {\n return;\n }\n\n var material = renderable.material;\n var program = renderable.__program;\n var roughness = material.get('roughness');\n\n if (roughness == null) {\n roughness = 1;\n }\n\n var normalMap = material.get('normalMap') || defaultNormalMap;\n var roughnessMap = material.get('roughnessMap');\n var bumpMap = material.get('bumpMap');\n var uvRepeat = material.get('uvRepeat');\n var uvOffset = material.get('uvOffset');\n var detailUvRepeat = material.get('detailUvRepeat');\n var detailUvOffset = material.get('detailUvOffset');\n var useBumpMap = !!bumpMap && material.isTextureEnabled('bumpMap');\n var useRoughnessMap = !!roughnessMap && material.isTextureEnabled('roughnessMap');\n var doubleSide = material.isDefined('fragment', 'DOUBLE_SIDED');\n bumpMap = bumpMap || defaultBumpMap;\n roughnessMap = roughnessMap || defaultRoughnessMap;\n\n if (prevNormalMaterial !== normalMaterial) {\n normalMaterial.set('normalMap', normalMap);\n normalMaterial.set('bumpMap', bumpMap);\n normalMaterial.set('roughnessMap', roughnessMap);\n normalMaterial.set('useBumpMap', useBumpMap);\n normalMaterial.set('useRoughnessMap', useRoughnessMap);\n normalMaterial.set('doubleSide', doubleSide);\n uvRepeat != null && normalMaterial.set('uvRepeat', uvRepeat);\n uvOffset != null && normalMaterial.set('uvOffset', uvOffset);\n detailUvRepeat != null && normalMaterial.set('detailUvRepeat', detailUvRepeat);\n detailUvOffset != null && normalMaterial.set('detailUvOffset', detailUvOffset);\n normalMaterial.set('roughness', roughness);\n } else {\n program.setUniform(gl, '1f', 'roughness', roughness);\n\n if (previousNormalMap !== normalMap) {\n attachTextureToSlot(renderer, program, 'normalMap', normalMap, 0);\n }\n\n if (previousBumpMap !== bumpMap && bumpMap) {\n attachTextureToSlot(renderer, program, 'bumpMap', bumpMap, 1);\n }\n\n if (previousRoughnessMap !== roughnessMap && roughnessMap) {\n attachTextureToSlot(renderer, program, 'roughnessMap', roughnessMap, 2);\n }\n\n if (uvRepeat != null) {\n program.setUniform(gl, '2f', 'uvRepeat', uvRepeat);\n }\n\n if (uvOffset != null) {\n program.setUniform(gl, '2f', 'uvOffset', uvOffset);\n }\n\n if (detailUvRepeat != null) {\n program.setUniform(gl, '2f', 'detailUvRepeat', detailUvRepeat);\n }\n\n if (detailUvOffset != null) {\n program.setUniform(gl, '2f', 'detailUvOffset', detailUvOffset);\n }\n\n program.setUniform(gl, '1i', 'useBumpMap', +useBumpMap);\n program.setUniform(gl, '1i', 'useRoughnessMap', +useRoughnessMap);\n program.setUniform(gl, '1i', 'doubleSide', +doubleSide);\n }\n\n previousNormalMap = normalMap;\n previousBumpMap = bumpMap;\n previousRoughnessMap = roughnessMap;\n previousRenderable = renderable;\n };\n}\n\nfunction NormalPass(opt) {\n opt = opt || {};\n this._depthTex = new Texture2D({\n format: Texture.DEPTH_COMPONENT,\n type: Texture.UNSIGNED_INT\n });\n this._normalTex = new Texture2D({\n type: Texture.HALF_FLOAT\n });\n this._framebuffer = new FrameBuffer();\n\n this._framebuffer.attach(this._normalTex);\n\n this._framebuffer.attach(this._depthTex, FrameBuffer.DEPTH_ATTACHMENT);\n\n this._normalMaterial = new Material({\n shader: new Shader(Shader.source('ecgl.normal.vertex'), Shader.source('ecgl.normal.fragment'))\n });\n\n this._normalMaterial.enableTexture(['normalMap', 'bumpMap', 'roughnessMap']);\n\n this._defaultNormalMap = textureUtil.createBlank('#000');\n this._defaultBumpMap = textureUtil.createBlank('#000');\n this._defaultRoughessMap = textureUtil.createBlank('#000');\n this._debugPass = new Pass({\n fragment: Shader.source('clay.compositor.output')\n });\n\n this._debugPass.setUniform('texture', this._normalTex);\n\n this._debugPass.material.undefine('fragment', 'OUTPUT_ALPHA');\n}\n\nNormalPass.prototype.getDepthTexture = function () {\n return this._depthTex;\n};\n\nNormalPass.prototype.getNormalTexture = function () {\n return this._normalTex;\n};\n\nNormalPass.prototype.update = function (renderer, scene, camera) {\n var width = renderer.getWidth();\n var height = renderer.getHeight();\n var depthTexture = this._depthTex;\n var normalTexture = this._normalTex;\n var normalMaterial = this._normalMaterial;\n depthTexture.width = width;\n depthTexture.height = height;\n normalTexture.width = width;\n normalTexture.height = height;\n var opaqueList = scene.getRenderList(camera).opaque;\n\n this._framebuffer.bind(renderer);\n\n renderer.gl.clearColor(0, 0, 0, 0);\n renderer.gl.clear(renderer.gl.COLOR_BUFFER_BIT | renderer.gl.DEPTH_BUFFER_BIT);\n renderer.gl.disable(renderer.gl.BLEND);\n renderer.renderPass(opaqueList, camera, {\n getMaterial: function () {\n return normalMaterial;\n },\n ifRender: function (object) {\n return object.renderNormal;\n },\n beforeRender: getBeforeRenderHook(renderer, this._defaultNormalMap, this._defaultBumpMap, this._defaultRoughessMap, this._normalMaterial),\n sort: renderer.opaqueSortCompare\n });\n\n this._framebuffer.unbind(renderer);\n};\n\nNormalPass.prototype.renderDebug = function (renderer) {\n this._debugPass.render(renderer);\n};\n\nNormalPass.prototype.dispose = function (renderer) {\n this._depthTex.dispose(renderer);\n\n this._normalTex.dispose(renderer);\n};\n\nexport default NormalPass;","import Matrix4 from 'claygl/src/math/Matrix4';\nimport Vector3 from 'claygl/src/math/Vector3';\nimport Texture2D from 'claygl/src/Texture2D';\nimport Texture from 'claygl/src/Texture';\nimport Pass from 'claygl/src/compositor/Pass';\nimport Shader from 'claygl/src/Shader';\nimport FrameBuffer from 'claygl/src/FrameBuffer';\n\nfunction EdgePass(opt) {\n opt = opt || {};\n this._edgePass = new Pass({\n fragment: Shader.source('ecgl.edge')\n });\n\n this._edgePass.setUniform('normalTexture', opt.normalTexture);\n\n this._edgePass.setUniform('depthTexture', opt.depthTexture);\n\n this._targetTexture = new Texture2D({\n type: Texture.HALF_FLOAT\n });\n this._frameBuffer = new FrameBuffer();\n\n this._frameBuffer.attach(this._targetTexture);\n}\n\nEdgePass.prototype.update = function (renderer, camera, sourceTexture, frame) {\n var width = renderer.getWidth();\n var height = renderer.getHeight();\n var texture = this._targetTexture;\n texture.width = width;\n texture.height = height;\n var frameBuffer = this._frameBuffer;\n frameBuffer.bind(renderer);\n\n this._edgePass.setUniform('projectionInv', camera.invProjectionMatrix.array);\n\n this._edgePass.setUniform('textureSize', [width, height]);\n\n this._edgePass.setUniform('texture', sourceTexture);\n\n this._edgePass.render(renderer);\n\n frameBuffer.unbind(renderer);\n};\n\nEdgePass.prototype.getTargetTexture = function () {\n return this._targetTexture;\n};\n\nEdgePass.prototype.setParameter = function (name, val) {\n this._edgePass.setUniform(name, val);\n};\n\nEdgePass.prototype.dispose = function (renderer) {\n this._targetTexture.dispose(renderer);\n\n this._frameBuffer.dispose(renderer);\n};\n\nexport default EdgePass;","export default {\n 'type': 'compositor',\n 'nodes': [{\n 'name': 'source',\n 'type': 'texture',\n 'outputs': {\n 'color': {}\n }\n }, {\n 'name': 'source_half',\n 'shader': '#source(clay.compositor.downsample)',\n 'inputs': {\n 'texture': 'source'\n },\n 'outputs': {\n 'color': {\n 'parameters': {\n 'width': 'expr(width * 1.0 / 2)',\n 'height': 'expr(height * 1.0 / 2)',\n 'type': 'HALF_FLOAT'\n }\n }\n },\n 'parameters': {\n 'textureSize': 'expr( [width * 1.0, height * 1.0] )'\n }\n }, {\n 'name': 'bright',\n 'shader': '#source(clay.compositor.bright)',\n 'inputs': {\n 'texture': 'source_half'\n },\n 'outputs': {\n 'color': {\n 'parameters': {\n 'width': 'expr(width * 1.0 / 2)',\n 'height': 'expr(height * 1.0 / 2)',\n 'type': 'HALF_FLOAT'\n }\n }\n },\n 'parameters': {\n 'threshold': 2,\n 'scale': 4,\n 'textureSize': 'expr([width * 1.0 / 2, height / 2])'\n }\n }, {\n 'name': 'bright_downsample_4',\n 'shader': '#source(clay.compositor.downsample)',\n 'inputs': {\n 'texture': 'bright'\n },\n 'outputs': {\n 'color': {\n 'parameters': {\n 'width': 'expr(width * 1.0 / 4)',\n 'height': 'expr(height * 1.0 / 4)',\n 'type': 'HALF_FLOAT'\n }\n }\n },\n 'parameters': {\n 'textureSize': 'expr( [width * 1.0 / 2, height / 2] )'\n }\n }, {\n 'name': 'bright_downsample_8',\n 'shader': '#source(clay.compositor.downsample)',\n 'inputs': {\n 'texture': 'bright_downsample_4'\n },\n 'outputs': {\n 'color': {\n 'parameters': {\n 'width': 'expr(width * 1.0 / 8)',\n 'height': 'expr(height * 1.0 / 8)',\n 'type': 'HALF_FLOAT'\n }\n }\n },\n 'parameters': {\n 'textureSize': 'expr( [width * 1.0 / 4, height / 4] )'\n }\n }, {\n 'name': 'bright_downsample_16',\n 'shader': '#source(clay.compositor.downsample)',\n 'inputs': {\n 'texture': 'bright_downsample_8'\n },\n 'outputs': {\n 'color': {\n 'parameters': {\n 'width': 'expr(width * 1.0 / 16)',\n 'height': 'expr(height * 1.0 / 16)',\n 'type': 'HALF_FLOAT'\n }\n }\n },\n 'parameters': {\n 'textureSize': 'expr( [width * 1.0 / 8, height / 8] )'\n }\n }, {\n 'name': 'bright_downsample_32',\n 'shader': '#source(clay.compositor.downsample)',\n 'inputs': {\n 'texture': 'bright_downsample_16'\n },\n 'outputs': {\n 'color': {\n 'parameters': {\n 'width': 'expr(width * 1.0 / 32)',\n 'height': 'expr(height * 1.0 / 32)',\n 'type': 'HALF_FLOAT'\n }\n }\n },\n 'parameters': {\n 'textureSize': 'expr( [width * 1.0 / 16, height / 16] )'\n }\n }, {\n 'name': 'bright_upsample_16_blur_h',\n 'shader': '#source(clay.compositor.gaussian_blur)',\n 'inputs': {\n 'texture': 'bright_downsample_32'\n },\n 'outputs': {\n 'color': {\n 'parameters': {\n 'width': 'expr(width * 1.0 / 16)',\n 'height': 'expr(height * 1.0 / 16)',\n 'type': 'HALF_FLOAT'\n }\n }\n },\n 'parameters': {\n 'blurSize': 1,\n 'blurDir': 0.0,\n 'textureSize': 'expr( [width * 1.0 / 32, height / 32] )'\n }\n }, {\n 'name': 'bright_upsample_16_blur_v',\n 'shader': '#source(clay.compositor.gaussian_blur)',\n 'inputs': {\n 'texture': 'bright_upsample_16_blur_h'\n },\n 'outputs': {\n 'color': {\n 'parameters': {\n 'width': 'expr(width * 1.0 / 16)',\n 'height': 'expr(height * 1.0 / 16)',\n 'type': 'HALF_FLOAT'\n }\n }\n },\n 'parameters': {\n 'blurSize': 1,\n 'blurDir': 1.0,\n 'textureSize': 'expr( [width * 1.0 / 16, height * 1.0 / 16] )'\n }\n }, {\n 'name': 'bright_upsample_8_blur_h',\n 'shader': '#source(clay.compositor.gaussian_blur)',\n 'inputs': {\n 'texture': 'bright_downsample_16'\n },\n 'outputs': {\n 'color': {\n 'parameters': {\n 'width': 'expr(width * 1.0 / 8)',\n 'height': 'expr(height * 1.0 / 8)',\n 'type': 'HALF_FLOAT'\n }\n }\n },\n 'parameters': {\n 'blurSize': 1,\n 'blurDir': 0.0,\n 'textureSize': 'expr( [width * 1.0 / 16, height * 1.0 / 16] )'\n }\n }, {\n 'name': 'bright_upsample_8_blur_v',\n 'shader': '#source(clay.compositor.gaussian_blur)',\n 'inputs': {\n 'texture': 'bright_upsample_8_blur_h'\n },\n 'outputs': {\n 'color': {\n 'parameters': {\n 'width': 'expr(width * 1.0 / 8)',\n 'height': 'expr(height * 1.0 / 8)',\n 'type': 'HALF_FLOAT'\n }\n }\n },\n 'parameters': {\n 'blurSize': 1,\n 'blurDir': 1.0,\n 'textureSize': 'expr( [width * 1.0 / 8, height * 1.0 / 8] )'\n }\n }, {\n 'name': 'bright_upsample_8_blend',\n 'shader': '#source(clay.compositor.blend)',\n 'inputs': {\n 'texture1': 'bright_upsample_8_blur_v',\n 'texture2': 'bright_upsample_16_blur_v'\n },\n 'outputs': {\n 'color': {\n 'parameters': {\n 'width': 'expr(width * 1.0 / 8)',\n 'height': 'expr(height * 1.0 / 8)',\n 'type': 'HALF_FLOAT'\n }\n }\n },\n 'parameters': {\n 'weight1': 0.3,\n 'weight2': 0.7\n }\n }, {\n 'name': 'bright_upsample_4_blur_h',\n 'shader': '#source(clay.compositor.gaussian_blur)',\n 'inputs': {\n 'texture': 'bright_downsample_8'\n },\n 'outputs': {\n 'color': {\n 'parameters': {\n 'width': 'expr(width * 1.0 / 4)',\n 'height': 'expr(height * 1.0 / 4)',\n 'type': 'HALF_FLOAT'\n }\n }\n },\n 'parameters': {\n 'blurSize': 1,\n 'blurDir': 0.0,\n 'textureSize': 'expr( [width * 1.0 / 8, height * 1.0 / 8] )'\n }\n }, {\n 'name': 'bright_upsample_4_blur_v',\n 'shader': '#source(clay.compositor.gaussian_blur)',\n 'inputs': {\n 'texture': 'bright_upsample_4_blur_h'\n },\n 'outputs': {\n 'color': {\n 'parameters': {\n 'width': 'expr(width * 1.0 / 4)',\n 'height': 'expr(height * 1.0 / 4)',\n 'type': 'HALF_FLOAT'\n }\n }\n },\n 'parameters': {\n 'blurSize': 1,\n 'blurDir': 1.0,\n 'textureSize': 'expr( [width * 1.0 / 4, height * 1.0 / 4] )'\n }\n }, {\n 'name': 'bright_upsample_4_blend',\n 'shader': '#source(clay.compositor.blend)',\n 'inputs': {\n 'texture1': 'bright_upsample_4_blur_v',\n 'texture2': 'bright_upsample_8_blend'\n },\n 'outputs': {\n 'color': {\n 'parameters': {\n 'width': 'expr(width * 1.0 / 4)',\n 'height': 'expr(height * 1.0 / 4)',\n 'type': 'HALF_FLOAT'\n }\n }\n },\n 'parameters': {\n 'weight1': 0.3,\n 'weight2': 0.7\n }\n }, {\n 'name': 'bright_upsample_2_blur_h',\n 'shader': '#source(clay.compositor.gaussian_blur)',\n 'inputs': {\n 'texture': 'bright_downsample_4'\n },\n 'outputs': {\n 'color': {\n 'parameters': {\n 'width': 'expr(width * 1.0 / 2)',\n 'height': 'expr(height * 1.0 / 2)',\n 'type': 'HALF_FLOAT'\n }\n }\n },\n 'parameters': {\n 'blurSize': 1,\n 'blurDir': 0.0,\n 'textureSize': 'expr( [width * 1.0 / 4, height * 1.0 / 4] )'\n }\n }, {\n 'name': 'bright_upsample_2_blur_v',\n 'shader': '#source(clay.compositor.gaussian_blur)',\n 'inputs': {\n 'texture': 'bright_upsample_2_blur_h'\n },\n 'outputs': {\n 'color': {\n 'parameters': {\n 'width': 'expr(width * 1.0 / 2)',\n 'height': 'expr(height * 1.0 / 2)',\n 'type': 'HALF_FLOAT'\n }\n }\n },\n 'parameters': {\n 'blurSize': 1,\n 'blurDir': 1.0,\n 'textureSize': 'expr( [width * 1.0 / 2, height * 1.0 / 2] )'\n }\n }, {\n 'name': 'bright_upsample_2_blend',\n 'shader': '#source(clay.compositor.blend)',\n 'inputs': {\n 'texture1': 'bright_upsample_2_blur_v',\n 'texture2': 'bright_upsample_4_blend'\n },\n 'outputs': {\n 'color': {\n 'parameters': {\n 'width': 'expr(width * 1.0 / 2)',\n 'height': 'expr(height * 1.0 / 2)',\n 'type': 'HALF_FLOAT'\n }\n }\n },\n 'parameters': {\n 'weight1': 0.3,\n 'weight2': 0.7\n }\n }, {\n 'name': 'bright_upsample_full_blur_h',\n 'shader': '#source(clay.compositor.gaussian_blur)',\n 'inputs': {\n 'texture': 'bright'\n },\n 'outputs': {\n 'color': {\n 'parameters': {\n 'width': 'expr(width * 1.0)',\n 'height': 'expr(height * 1.0)',\n 'type': 'HALF_FLOAT'\n }\n }\n },\n 'parameters': {\n 'blurSize': 1,\n 'blurDir': 0.0,\n 'textureSize': 'expr( [width * 1.0 / 2, height * 1.0 / 2] )'\n }\n }, {\n 'name': 'bright_upsample_full_blur_v',\n 'shader': '#source(clay.compositor.gaussian_blur)',\n 'inputs': {\n 'texture': 'bright_upsample_full_blur_h'\n },\n 'outputs': {\n 'color': {\n 'parameters': {\n 'width': 'expr(width * 1.0)',\n 'height': 'expr(height * 1.0)',\n 'type': 'HALF_FLOAT'\n }\n }\n },\n 'parameters': {\n 'blurSize': 1,\n 'blurDir': 1.0,\n 'textureSize': 'expr( [width * 1.0, height * 1.0] )'\n }\n }, {\n 'name': 'bloom_composite',\n 'shader': '#source(clay.compositor.blend)',\n 'inputs': {\n 'texture1': 'bright_upsample_full_blur_v',\n 'texture2': 'bright_upsample_2_blend'\n },\n 'outputs': {\n 'color': {\n 'parameters': {\n 'width': 'expr(width * 1.0)',\n 'height': 'expr(height * 1.0)',\n 'type': 'HALF_FLOAT'\n }\n }\n },\n 'parameters': {\n 'weight1': 0.3,\n 'weight2': 0.7\n }\n }, {\n 'name': 'coc',\n 'shader': '#source(ecgl.dof.coc)',\n 'outputs': {\n 'color': {\n 'parameters': {\n 'minFilter': 'NEAREST',\n 'magFilter': 'NEAREST',\n 'width': 'expr(width * 1.0)',\n 'height': 'expr(height * 1.0)'\n }\n }\n },\n 'parameters': {\n 'focalDist': 50,\n 'focalRange': 30\n }\n }, {\n 'name': 'dof_far_blur',\n 'shader': '#source(ecgl.dof.diskBlur)',\n 'inputs': {\n 'texture': 'source',\n 'coc': 'coc'\n },\n 'outputs': {\n 'color': {\n 'parameters': {\n 'width': 'expr(width * 1.0)',\n 'height': 'expr(height * 1.0)',\n 'type': 'HALF_FLOAT'\n }\n }\n },\n 'parameters': {\n 'textureSize': 'expr( [width * 1.0, height * 1.0] )'\n }\n }, {\n 'name': 'dof_near_blur',\n 'shader': '#source(ecgl.dof.diskBlur)',\n 'inputs': {\n 'texture': 'source',\n 'coc': 'coc'\n },\n 'outputs': {\n 'color': {\n 'parameters': {\n 'width': 'expr(width * 1.0)',\n 'height': 'expr(height * 1.0)',\n 'type': 'HALF_FLOAT'\n }\n }\n },\n 'parameters': {\n 'textureSize': 'expr( [width * 1.0, height * 1.0] )'\n },\n 'defines': {\n 'BLUR_NEARFIELD': null\n }\n }, {\n 'name': 'dof_coc_blur',\n 'shader': '#source(ecgl.dof.diskBlur)',\n 'inputs': {\n 'texture': 'coc'\n },\n 'outputs': {\n 'color': {\n 'parameters': {\n 'minFilter': 'NEAREST',\n 'magFilter': 'NEAREST',\n 'width': 'expr(width * 1.0)',\n 'height': 'expr(height * 1.0)'\n }\n }\n },\n 'parameters': {\n 'textureSize': 'expr( [width * 1.0, height * 1.0] )'\n },\n 'defines': {\n 'BLUR_COC': null\n }\n }, {\n 'name': 'dof_composite',\n 'shader': '#source(ecgl.dof.composite)',\n 'inputs': {\n 'original': 'source',\n 'blurred': 'dof_far_blur',\n 'nearfield': 'dof_near_blur',\n 'coc': 'coc',\n 'nearcoc': 'dof_coc_blur'\n },\n 'outputs': {\n 'color': {\n 'parameters': {\n 'width': 'expr(width * 1.0)',\n 'height': 'expr(height * 1.0)',\n 'type': 'HALF_FLOAT'\n }\n }\n }\n }, {\n 'name': 'composite',\n 'shader': '#source(clay.compositor.hdr.composite)',\n 'inputs': {\n 'texture': 'source',\n 'bloom': 'bloom_composite'\n },\n 'outputs': {\n 'color': {\n 'parameters': {\n 'width': 'expr(width * 1.0)',\n 'height': 'expr(height * 1.0)'\n }\n }\n },\n 'defines': {// Images are all premultiplied alpha before composite because of blending.\n // 'PREMULTIPLY_ALPHA': null,\n // 'DEBUG': 2\n }\n }, {\n 'name': 'FXAA',\n 'shader': '#source(clay.compositor.fxaa)',\n 'inputs': {\n 'texture': 'composite'\n }\n }]\n};","export default \"@export ecgl.dof.coc\\n\\nuniform sampler2D depth;\\n\\nuniform float zNear: 0.1;\\nuniform float zFar: 2000;\\n\\nuniform float focalDistance: 3;\\nuniform float focalRange: 1;\\nuniform float focalLength: 30;\\nuniform float fstop: 2.8;\\n\\nvarying vec2 v_Texcoord;\\n\\n@import clay.util.encode_float\\n\\nvoid main()\\n{\\n float z = texture2D(depth, v_Texcoord).r * 2.0 - 1.0;\\n\\n float dist = 2.0 * zNear * zFar / (zFar + zNear - z * (zFar - zNear));\\n\\n float aperture = focalLength / fstop;\\n\\n float coc;\\n\\n float uppper = focalDistance + focalRange;\\n float lower = focalDistance - focalRange;\\n if (dist <= uppper && dist >= lower) {\\n coc = 0.5;\\n }\\n else {\\n float focalAdjusted = dist > uppper ? uppper : lower;\\n\\n coc = abs(aperture * (focalLength * (dist - focalAdjusted)) / (dist * (focalAdjusted - focalLength)));\\n coc = clamp(coc, 0.0, 2.0) / 2.00001;\\n\\n if (dist < lower) {\\n coc = -coc;\\n }\\n coc = coc * 0.5 + 0.5;\\n }\\n\\n gl_FragColor = encodeFloat(coc);\\n}\\n@end\\n\\n\\n@export ecgl.dof.composite\\n\\n#define DEBUG 0\\n\\nuniform sampler2D original;\\nuniform sampler2D blurred;\\nuniform sampler2D nearfield;\\nuniform sampler2D coc;\\nuniform sampler2D nearcoc;\\nvarying vec2 v_Texcoord;\\n\\n@import clay.util.rgbm\\n@import clay.util.float\\n\\nvoid main()\\n{\\n vec4 blurredColor = texture2D(blurred, v_Texcoord);\\n vec4 originalColor = texture2D(original, v_Texcoord);\\n\\n float fCoc = decodeFloat(texture2D(coc, v_Texcoord));\\n\\n fCoc = abs(fCoc * 2.0 - 1.0);\\n\\n float weight = smoothstep(0.0, 1.0, fCoc);\\n \\n#ifdef NEARFIELD_ENABLED\\n vec4 nearfieldColor = texture2D(nearfield, v_Texcoord);\\n float fNearCoc = decodeFloat(texture2D(nearcoc, v_Texcoord));\\n fNearCoc = abs(fNearCoc * 2.0 - 1.0);\\n\\n gl_FragColor = encodeHDR(\\n mix(\\n nearfieldColor, mix(originalColor, blurredColor, weight),\\n pow(1.0 - fNearCoc, 4.0)\\n )\\n );\\n#else\\n gl_FragColor = encodeHDR(mix(originalColor, blurredColor, weight));\\n#endif\\n\\n}\\n\\n@end\\n\\n\\n\\n@export ecgl.dof.diskBlur\\n\\n#define POISSON_KERNEL_SIZE 16;\\n\\nuniform sampler2D texture;\\nuniform sampler2D coc;\\nvarying vec2 v_Texcoord;\\n\\nuniform float blurRadius : 10.0;\\nuniform vec2 textureSize : [512.0, 512.0];\\n\\nuniform vec2 poissonKernel[POISSON_KERNEL_SIZE];\\n\\nuniform float percent;\\n\\nfloat nrand(const in vec2 n) {\\n return fract(sin(dot(n.xy ,vec2(12.9898,78.233))) * 43758.5453);\\n}\\n\\n@import clay.util.rgbm\\n@import clay.util.float\\n\\n\\nvoid main()\\n{\\n vec2 offset = blurRadius / textureSize;\\n\\n float rnd = 6.28318 * nrand(v_Texcoord + 0.07 * percent );\\n float cosa = cos(rnd);\\n float sina = sin(rnd);\\n vec4 basis = vec4(cosa, -sina, sina, cosa);\\n\\n#if !defined(BLUR_NEARFIELD) && !defined(BLUR_COC)\\n offset *= abs(decodeFloat(texture2D(coc, v_Texcoord)) * 2.0 - 1.0);\\n#endif\\n\\n#ifdef BLUR_COC\\n float cocSum = 0.0;\\n#else\\n vec4 color = vec4(0.0);\\n#endif\\n\\n\\n float weightSum = 0.0;\\n\\n for (int i = 0; i < POISSON_KERNEL_SIZE; i++) {\\n vec2 ofs = poissonKernel[i];\\n\\n ofs = vec2(dot(ofs, basis.xy), dot(ofs, basis.zw));\\n\\n vec2 uv = v_Texcoord + ofs * offset;\\n vec4 texel = texture2D(texture, uv);\\n\\n float w = 1.0;\\n#ifdef BLUR_COC\\n float fCoc = decodeFloat(texel) * 2.0 - 1.0;\\n cocSum += clamp(fCoc, -1.0, 0.0) * w;\\n#else\\n texel = texel;\\n #if !defined(BLUR_NEARFIELD)\\n float fCoc = decodeFloat(texture2D(coc, uv)) * 2.0 - 1.0;\\n w *= abs(fCoc);\\n #endif\\n texel.rgb *= texel.a;\\n color += texel * w;\\n#endif\\n\\n weightSum += w;\\n }\\n\\n#ifdef BLUR_COC\\n gl_FragColor = encodeFloat(clamp(cocSum / weightSum, -1.0, 0.0) * 0.5 + 0.5);\\n#else\\n color /= weightSum;\\n color.rgb /= (color.a + 0.0001);\\n gl_FragColor = color;\\n#endif\\n}\\n\\n@end\";","export default \"@export ecgl.edge\\n\\nuniform sampler2D texture;\\n\\nuniform sampler2D normalTexture;\\nuniform sampler2D depthTexture;\\n\\nuniform mat4 projectionInv;\\n\\nuniform vec2 textureSize;\\n\\nuniform vec4 edgeColor: [0,0,0,0.8];\\n\\nvarying vec2 v_Texcoord;\\n\\nvec3 packColor(vec2 coord) {\\n float z = texture2D(depthTexture, coord).r * 2.0 - 1.0;\\n vec4 p = vec4(v_Texcoord * 2.0 - 1.0, z, 1.0);\\n vec4 p4 = projectionInv * p;\\n\\n return vec3(\\n texture2D(normalTexture, coord).rg,\\n -p4.z / p4.w / 5.0\\n );\\n}\\n\\nvoid main() {\\n vec2 cc = v_Texcoord;\\n vec3 center = packColor(cc);\\n\\n float size = clamp(1.0 - (center.z - 10.0) / 100.0, 0.0, 1.0) * 0.5;\\n float dx = size / textureSize.x;\\n float dy = size / textureSize.y;\\n\\n vec2 coord;\\n vec3 topLeft = packColor(cc+vec2(-dx, -dy));\\n vec3 top = packColor(cc+vec2(0.0, -dy));\\n vec3 topRight = packColor(cc+vec2(dx, -dy));\\n vec3 left = packColor(cc+vec2(-dx, 0.0));\\n vec3 right = packColor(cc+vec2(dx, 0.0));\\n vec3 bottomLeft = packColor(cc+vec2(-dx, dy));\\n vec3 bottom = packColor(cc+vec2(0.0, dy));\\n vec3 bottomRight = packColor(cc+vec2(dx, dy));\\n\\n vec3 v = -topLeft-2.0*top-topRight+bottomLeft+2.0*bottom+bottomRight;\\n vec3 h = -bottomLeft-2.0*left-topLeft+bottomRight+2.0*right+topRight;\\n\\n float edge = sqrt(dot(h, h) + dot(v, v));\\n\\n edge = smoothstep(0.8, 1.0, edge);\\n\\n gl_FragColor = mix(texture2D(texture, v_Texcoord), vec4(edgeColor.rgb, 1.0), edgeColor.a * edge);\\n}\\n@end\";","import Shader from 'claygl/src/Shader';\nimport Texture2D from 'claygl/src/Texture2D';\nimport Texture from 'claygl/src/Texture';\nimport FrameBuffer from 'claygl/src/FrameBuffer';\nimport createCompositor from 'claygl/src/compositor/createCompositor';\nimport SSAOPass from './SSAOPass';\nimport SSRPass from './SSRPass';\nimport poissonKernel from './poissonKernel';\nimport graphicGL from '../util/graphicGL';\nimport NormalPass from './NormalPass';\nimport EdgePass from './EdgePass';\nimport effectJson from './composite.js';\nimport blurCode from 'claygl/src/shader/source/compositor/blur.glsl.js';\nimport lutCode from 'claygl/src/shader/source/compositor/lut.glsl.js';\nimport outputCode from 'claygl/src/shader/source/compositor/output.glsl.js';\nimport brightCode from 'claygl/src/shader/source/compositor/bright.glsl.js';\nimport downsampleCode from 'claygl/src/shader/source/compositor/downsample.glsl.js';\nimport upsampleCode from 'claygl/src/shader/source/compositor/upsample.glsl.js';\nimport hdrCode from 'claygl/src/shader/source/compositor/hdr.glsl.js';\nimport blendCode from 'claygl/src/shader/source/compositor/blend.glsl.js';\nimport fxaaCode from 'claygl/src/shader/source/compositor/fxaa.glsl.js';\nimport DOFCode from './DOF.glsl.js';\nimport edgeCode from './edge.glsl.js';\nShader['import'](blurCode);\nShader['import'](lutCode);\nShader['import'](outputCode);\nShader['import'](brightCode);\nShader['import'](downsampleCode);\nShader['import'](upsampleCode);\nShader['import'](hdrCode);\nShader['import'](blendCode);\nShader['import'](fxaaCode);\nShader['import'](DOFCode);\nShader['import'](edgeCode);\n\nfunction makeCommonOutputs(getWidth, getHeight) {\n return {\n color: {\n parameters: {\n width: getWidth,\n height: getHeight\n }\n }\n };\n}\n\nvar FINAL_NODES_CHAIN = ['composite', 'FXAA'];\n\nfunction EffectCompositor() {\n this._width;\n this._height;\n this._dpr;\n this._sourceTexture = new Texture2D({\n type: Texture.HALF_FLOAT\n });\n this._depthTexture = new Texture2D({\n format: Texture.DEPTH_COMPONENT,\n type: Texture.UNSIGNED_INT\n });\n this._framebuffer = new FrameBuffer();\n\n this._framebuffer.attach(this._sourceTexture);\n\n this._framebuffer.attach(this._depthTexture, FrameBuffer.DEPTH_ATTACHMENT);\n\n this._normalPass = new NormalPass();\n this._compositor = createCompositor(effectJson);\n\n var sourceNode = this._compositor.getNodeByName('source');\n\n sourceNode.texture = this._sourceTexture;\n\n var cocNode = this._compositor.getNodeByName('coc');\n\n this._sourceNode = sourceNode;\n this._cocNode = cocNode;\n this._compositeNode = this._compositor.getNodeByName('composite');\n this._fxaaNode = this._compositor.getNodeByName('FXAA');\n this._dofBlurNodes = ['dof_far_blur', 'dof_near_blur', 'dof_coc_blur'].map(function (name) {\n return this._compositor.getNodeByName(name);\n }, this);\n this._dofBlurKernel = 0;\n this._dofBlurKernelSize = new Float32Array(0);\n this._finalNodesChain = FINAL_NODES_CHAIN.map(function (name) {\n return this._compositor.getNodeByName(name);\n }, this);\n var gBufferObj = {\n normalTexture: this._normalPass.getNormalTexture(),\n depthTexture: this._normalPass.getDepthTexture()\n };\n this._ssaoPass = new SSAOPass(gBufferObj);\n this._ssrPass = new SSRPass(gBufferObj);\n this._edgePass = new EdgePass(gBufferObj);\n}\n\nEffectCompositor.prototype.resize = function (width, height, dpr) {\n dpr = dpr || 1;\n var width = width * dpr;\n var height = height * dpr;\n var sourceTexture = this._sourceTexture;\n var depthTexture = this._depthTexture;\n sourceTexture.width = width;\n sourceTexture.height = height;\n depthTexture.width = width;\n depthTexture.height = height;\n var rendererMock = {\n getWidth: function () {\n return width;\n },\n getHeight: function () {\n return height;\n },\n getDevicePixelRatio: function () {\n return dpr;\n }\n };\n\n function wrapCallback(obj, key) {\n if (typeof obj[key] === 'function') {\n var oldFunc = obj[key].__original || obj[key]; // Use viewport width/height instead of renderer width/height\n\n obj[key] = function (renderer) {\n return oldFunc.call(this, rendererMock);\n };\n\n obj[key].__original = oldFunc;\n }\n }\n\n this._compositor.nodes.forEach(function (node) {\n for (var outKey in node.outputs) {\n var parameters = node.outputs[outKey].parameters;\n\n if (parameters) {\n wrapCallback(parameters, 'width');\n wrapCallback(parameters, 'height');\n }\n }\n\n for (var paramKey in node.parameters) {\n wrapCallback(node.parameters, paramKey);\n }\n });\n\n this._width = width;\n this._height = height;\n this._dpr = dpr;\n};\n\nEffectCompositor.prototype.getWidth = function () {\n return this._width;\n};\n\nEffectCompositor.prototype.getHeight = function () {\n return this._height;\n};\n\nEffectCompositor.prototype._ifRenderNormalPass = function () {\n return this._enableSSAO || this._enableEdge || this._enableSSR;\n};\n\nEffectCompositor.prototype._getPrevNode = function (node) {\n var idx = FINAL_NODES_CHAIN.indexOf(node.name) - 1;\n var prevNode = this._finalNodesChain[idx];\n\n while (prevNode && !this._compositor.getNodeByName(prevNode.name)) {\n idx -= 1;\n prevNode = this._finalNodesChain[idx];\n }\n\n return prevNode;\n};\n\nEffectCompositor.prototype._getNextNode = function (node) {\n var idx = FINAL_NODES_CHAIN.indexOf(node.name) + 1;\n var nextNode = this._finalNodesChain[idx];\n\n while (nextNode && !this._compositor.getNodeByName(nextNode.name)) {\n idx += 1;\n nextNode = this._finalNodesChain[idx];\n }\n\n return nextNode;\n};\n\nEffectCompositor.prototype._addChainNode = function (node) {\n var prevNode = this._getPrevNode(node);\n\n var nextNode = this._getNextNode(node);\n\n if (!prevNode) {\n return;\n }\n\n node.inputs.texture = prevNode.name;\n\n if (nextNode) {\n node.outputs = makeCommonOutputs(this.getWidth.bind(this), this.getHeight.bind(this));\n nextNode.inputs.texture = node.name;\n } else {\n node.outputs = null;\n }\n\n this._compositor.addNode(node);\n};\n\nEffectCompositor.prototype._removeChainNode = function (node) {\n var prevNode = this._getPrevNode(node);\n\n var nextNode = this._getNextNode(node);\n\n if (!prevNode) {\n return;\n }\n\n if (nextNode) {\n prevNode.outputs = makeCommonOutputs(this.getWidth.bind(this), this.getHeight.bind(this));\n nextNode.inputs.texture = prevNode.name;\n } else {\n prevNode.outputs = null;\n }\n\n this._compositor.removeNode(node);\n};\n/**\n * Update normal\n */\n\n\nEffectCompositor.prototype.updateNormal = function (renderer, scene, camera, frame) {\n if (this._ifRenderNormalPass()) {\n this._normalPass.update(renderer, scene, camera);\n }\n};\n/**\n * Render SSAO after render the scene, before compositing\n */\n\n\nEffectCompositor.prototype.updateSSAO = function (renderer, scene, camera, frame) {\n this._ssaoPass.update(renderer, camera, frame);\n};\n/**\n * Enable SSAO effect\n */\n\n\nEffectCompositor.prototype.enableSSAO = function () {\n this._enableSSAO = true;\n};\n/**\n * Disable SSAO effect\n */\n\n\nEffectCompositor.prototype.disableSSAO = function () {\n this._enableSSAO = false;\n};\n/**\n * Enable SSR effect\n */\n\n\nEffectCompositor.prototype.enableSSR = function () {\n this._enableSSR = true; // this._normalPass.enableTargetTexture3 = true;\n};\n/**\n * Disable SSR effect\n */\n\n\nEffectCompositor.prototype.disableSSR = function () {\n this._enableSSR = false; // this._normalPass.enableTargetTexture3 = false;\n};\n/**\n * Render SSAO after render the scene, before compositing\n */\n\n\nEffectCompositor.prototype.getSSAOTexture = function () {\n return this._ssaoPass.getTargetTexture();\n};\n/**\n * @return {clay.FrameBuffer}\n */\n\n\nEffectCompositor.prototype.getSourceFrameBuffer = function () {\n return this._framebuffer;\n};\n/**\n * @return {clay.Texture2D}\n */\n\n\nEffectCompositor.prototype.getSourceTexture = function () {\n return this._sourceTexture;\n};\n/**\n * Disable fxaa effect\n */\n\n\nEffectCompositor.prototype.disableFXAA = function () {\n this._removeChainNode(this._fxaaNode);\n};\n/**\n * Enable fxaa effect\n */\n\n\nEffectCompositor.prototype.enableFXAA = function () {\n this._addChainNode(this._fxaaNode);\n};\n/**\n * Enable bloom effect\n */\n\n\nEffectCompositor.prototype.enableBloom = function () {\n this._compositeNode.inputs.bloom = 'bloom_composite';\n\n this._compositor.dirty();\n};\n/**\n * Disable bloom effect\n */\n\n\nEffectCompositor.prototype.disableBloom = function () {\n this._compositeNode.inputs.bloom = null;\n\n this._compositor.dirty();\n};\n/**\n * Enable depth of field effect\n */\n\n\nEffectCompositor.prototype.enableDOF = function () {\n this._compositeNode.inputs.texture = 'dof_composite';\n\n this._compositor.dirty();\n};\n/**\n * Disable depth of field effect\n */\n\n\nEffectCompositor.prototype.disableDOF = function () {\n this._compositeNode.inputs.texture = 'source';\n\n this._compositor.dirty();\n};\n/**\n * Enable color correction\n */\n\n\nEffectCompositor.prototype.enableColorCorrection = function () {\n this._compositeNode.define('COLOR_CORRECTION');\n\n this._enableColorCorrection = true;\n};\n/**\n * Disable color correction\n */\n\n\nEffectCompositor.prototype.disableColorCorrection = function () {\n this._compositeNode.undefine('COLOR_CORRECTION');\n\n this._enableColorCorrection = false;\n};\n/**\n * Enable edge detection\n */\n\n\nEffectCompositor.prototype.enableEdge = function () {\n this._enableEdge = true;\n};\n/**\n * Disable edge detection\n */\n\n\nEffectCompositor.prototype.disableEdge = function () {\n this._enableEdge = false;\n};\n/**\n * Set bloom intensity\n * @param {number} value\n */\n\n\nEffectCompositor.prototype.setBloomIntensity = function (value) {\n this._compositeNode.setParameter('bloomIntensity', value);\n};\n\nEffectCompositor.prototype.setSSAOParameter = function (name, value) {\n switch (name) {\n case 'quality':\n // PENDING\n var kernelSize = {\n low: 6,\n medium: 12,\n high: 32,\n ultra: 62\n }[value] || 12;\n\n this._ssaoPass.setParameter('kernelSize', kernelSize);\n\n break;\n\n case 'radius':\n this._ssaoPass.setParameter(name, value);\n\n this._ssaoPass.setParameter('bias', value / 200);\n\n break;\n\n case 'intensity':\n this._ssaoPass.setParameter(name, value);\n\n break;\n\n default:\n if (process.env.NODE_ENV !== 'production') {\n console.warn('Unkown SSAO parameter ' + name);\n }\n\n }\n};\n\nEffectCompositor.prototype.setDOFParameter = function (name, value) {\n switch (name) {\n case 'focalDistance':\n case 'focalRange':\n case 'fstop':\n this._cocNode.setParameter(name, value);\n\n break;\n\n case 'blurRadius':\n for (var i = 0; i < this._dofBlurNodes.length; i++) {\n this._dofBlurNodes[i].setParameter('blurRadius', value);\n }\n\n break;\n\n case 'quality':\n var kernelSize = {\n low: 4,\n medium: 8,\n high: 16,\n ultra: 32\n }[value] || 8;\n this._dofBlurKernelSize = kernelSize;\n\n for (var i = 0; i < this._dofBlurNodes.length; i++) {\n this._dofBlurNodes[i].pass.material.define('POISSON_KERNEL_SIZE', kernelSize);\n }\n\n this._dofBlurKernel = new Float32Array(kernelSize * 2);\n break;\n\n default:\n if (process.env.NODE_ENV !== 'production') {\n console.warn('Unkown DOF parameter ' + name);\n }\n\n }\n};\n\nEffectCompositor.prototype.setSSRParameter = function (name, value) {\n if (value == null) {\n return;\n }\n\n switch (name) {\n case 'quality':\n // PENDING\n var maxIteration = {\n low: 10,\n medium: 15,\n high: 30,\n ultra: 80\n }[value] || 20;\n var pixelStride = {\n low: 32,\n medium: 16,\n high: 8,\n ultra: 4\n }[value] || 16;\n\n this._ssrPass.setParameter('maxIteration', maxIteration);\n\n this._ssrPass.setParameter('pixelStride', pixelStride);\n\n break;\n\n case 'maxRoughness':\n this._ssrPass.setParameter('minGlossiness', Math.max(Math.min(1.0 - value, 1.0), 0.0));\n\n break;\n\n case 'physical':\n this.setPhysicallyCorrectSSR(value);\n break;\n\n default:\n console.warn('Unkown SSR parameter ' + name);\n }\n};\n\nEffectCompositor.prototype.setPhysicallyCorrectSSR = function (physical) {\n this._ssrPass.setPhysicallyCorrect(physical);\n};\n/**\n * Set color of edge\n */\n\n\nEffectCompositor.prototype.setEdgeColor = function (value) {\n var color = graphicGL.parseColor(value);\n\n this._edgePass.setParameter('edgeColor', color);\n};\n\nEffectCompositor.prototype.setExposure = function (value) {\n this._compositeNode.setParameter('exposure', Math.pow(2, value));\n};\n\nEffectCompositor.prototype.setColorLookupTexture = function (image, api) {\n this._compositeNode.pass.material.setTextureImage('lut', this._enableColorCorrection ? image : 'none', api, {\n minFilter: graphicGL.Texture.NEAREST,\n magFilter: graphicGL.Texture.NEAREST,\n flipY: false\n });\n};\n\nEffectCompositor.prototype.setColorCorrection = function (type, value) {\n this._compositeNode.setParameter(type, value);\n};\n\nEffectCompositor.prototype.isSSREnabled = function () {\n return this._enableSSR;\n};\n\nEffectCompositor.prototype.composite = function (renderer, scene, camera, framebuffer, frame) {\n var sourceTexture = this._sourceTexture;\n var targetTexture = sourceTexture;\n\n if (this._enableEdge) {\n this._edgePass.update(renderer, camera, sourceTexture, frame);\n\n sourceTexture = targetTexture = this._edgePass.getTargetTexture();\n }\n\n if (this._enableSSR) {\n this._ssrPass.update(renderer, camera, sourceTexture, frame);\n\n targetTexture = this._ssrPass.getTargetTexture();\n\n this._ssrPass.setSSAOTexture(this._enableSSAO ? this._ssaoPass.getTargetTexture() : null); // var lights = scene.getLights();\n // for (var i = 0; i < lights.length; i++) {\n // if (lights[i].cubemap) {\n // this._ssrPass.setAmbientCubemap(lights[i].cubemap, lights[i].intensity);\n // }\n // }\n\n }\n\n this._sourceNode.texture = targetTexture;\n\n this._cocNode.setParameter('depth', this._depthTexture);\n\n var blurKernel = this._dofBlurKernel;\n var blurKernelSize = this._dofBlurKernelSize;\n var frameAll = Math.floor(poissonKernel.length / 2 / blurKernelSize);\n var kernelOffset = frame % frameAll;\n\n for (var i = 0; i < blurKernelSize * 2; i++) {\n blurKernel[i] = poissonKernel[i + kernelOffset * blurKernelSize * 2];\n }\n\n for (var i = 0; i < this._dofBlurNodes.length; i++) {\n this._dofBlurNodes[i].setParameter('percent', frame / 30.0);\n\n this._dofBlurNodes[i].setParameter('poissonKernel', blurKernel);\n }\n\n this._cocNode.setParameter('zNear', camera.near);\n\n this._cocNode.setParameter('zFar', camera.far);\n\n this._compositor.render(renderer, framebuffer);\n};\n\nEffectCompositor.prototype.dispose = function (renderer) {\n this._sourceTexture.dispose(renderer);\n\n this._depthTexture.dispose(renderer);\n\n this._framebuffer.dispose(renderer);\n\n this._compositor.dispose(renderer);\n\n this._normalPass.dispose(renderer);\n\n this._ssaoPass.dispose(renderer);\n};\n\nexport default EffectCompositor;","// Temporal Super Sample for static Scene\nimport halton from './halton';\nimport Pass from 'claygl/src/compositor/Pass';\nimport FrameBuffer from 'claygl/src/FrameBuffer';\nimport Texture2D from 'claygl/src/Texture2D';\nimport Shader from 'claygl/src/Shader';\nimport Matrix4 from 'claygl/src/math/Matrix4';\n\nfunction TemporalSuperSampling(frames) {\n var haltonSequence = [];\n\n for (var i = 0; i < 30; i++) {\n haltonSequence.push([halton(i, 2), halton(i, 3)]);\n }\n\n this._haltonSequence = haltonSequence;\n this._frame = 0;\n this._sourceTex = new Texture2D();\n this._sourceFb = new FrameBuffer();\n\n this._sourceFb.attach(this._sourceTex); // Frame texture before temporal supersampling\n\n\n this._prevFrameTex = new Texture2D();\n this._outputTex = new Texture2D();\n var blendPass = this._blendPass = new Pass({\n fragment: Shader.source('clay.compositor.blend')\n });\n blendPass.material.disableTexturesAll();\n blendPass.material.enableTexture(['texture1', 'texture2']);\n this._blendFb = new FrameBuffer({\n depthBuffer: false\n });\n this._outputPass = new Pass({\n fragment: Shader.source('clay.compositor.output'),\n // TODO, alpha is premultiplied?\n blendWithPrevious: true\n });\n\n this._outputPass.material.define('fragment', 'OUTPUT_ALPHA');\n\n this._outputPass.material.blend = function (_gl) {\n // FIXME.\n // Output is premultiplied alpha when BLEND is enabled ?\n // http://stackoverflow.com/questions/2171085/opengl-blending-with-previous-contents-of-framebuffer\n _gl.blendEquationSeparate(_gl.FUNC_ADD, _gl.FUNC_ADD);\n\n _gl.blendFuncSeparate(_gl.ONE, _gl.ONE_MINUS_SRC_ALPHA, _gl.ONE, _gl.ONE_MINUS_SRC_ALPHA);\n };\n}\n\nTemporalSuperSampling.prototype = {\n constructor: TemporalSuperSampling,\n\n /**\n * Jitter camera projectionMatrix\n * @parma {clay.Renderer} renderer\n * @param {clay.Camera} camera\n */\n jitterProjection: function (renderer, camera) {\n var viewport = renderer.viewport;\n var dpr = viewport.devicePixelRatio || renderer.getDevicePixelRatio();\n var width = viewport.width * dpr;\n var height = viewport.height * dpr;\n var offset = this._haltonSequence[this._frame % this._haltonSequence.length];\n var translationMat = new Matrix4();\n translationMat.array[12] = (offset[0] * 2.0 - 1.0) / width;\n translationMat.array[13] = (offset[1] * 2.0 - 1.0) / height;\n Matrix4.mul(camera.projectionMatrix, translationMat, camera.projectionMatrix);\n Matrix4.invert(camera.invProjectionMatrix, camera.projectionMatrix);\n },\n\n /**\n * Reset accumulating frame\n */\n resetFrame: function () {\n this._frame = 0;\n },\n\n /**\n * Return current frame\n */\n getFrame: function () {\n return this._frame;\n },\n\n /**\n * Get source framebuffer for usage\n */\n getSourceFrameBuffer: function () {\n return this._sourceFb;\n },\n getOutputTexture: function () {\n return this._outputTex;\n },\n resize: function (width, height) {\n this._prevFrameTex.width = width;\n this._prevFrameTex.height = height;\n this._outputTex.width = width;\n this._outputTex.height = height;\n this._sourceTex.width = width;\n this._sourceTex.height = height;\n\n this._prevFrameTex.dirty();\n\n this._outputTex.dirty();\n\n this._sourceTex.dirty();\n },\n isFinished: function () {\n return this._frame >= this._haltonSequence.length;\n },\n render: function (renderer, sourceTex, notOutput) {\n var blendPass = this._blendPass;\n\n if (this._frame === 0) {\n // Direct output\n blendPass.setUniform('weight1', 0);\n blendPass.setUniform('weight2', 1);\n } else {\n blendPass.setUniform('weight1', 0.9);\n blendPass.setUniform('weight2', 0.1);\n }\n\n blendPass.setUniform('texture1', this._prevFrameTex);\n blendPass.setUniform('texture2', sourceTex || this._sourceTex);\n\n this._blendFb.attach(this._outputTex);\n\n this._blendFb.bind(renderer);\n\n blendPass.render(renderer);\n\n this._blendFb.unbind(renderer);\n\n if (!notOutput) {\n this._outputPass.setUniform('texture', this._outputTex);\n\n this._outputPass.render(renderer);\n } // Swap texture\n\n\n var tmp = this._prevFrameTex;\n this._prevFrameTex = this._outputTex;\n this._outputTex = tmp;\n this._frame++;\n },\n dispose: function (renderer) {\n this._sourceFb.dispose(renderer);\n\n this._blendFb.dispose(renderer);\n\n this._prevFrameTex.dispose(renderer);\n\n this._outputTex.dispose(renderer);\n\n this._sourceTex.dispose(renderer);\n\n this._outputPass.dispose(renderer);\n\n this._blendPass.dispose(renderer);\n }\n};\nexport default TemporalSuperSampling;","/*\n * @module echarts-gl/core/ViewGL\n * @author Yi Shen(http://github.com/pissang)\n */\nimport * as echarts from 'echarts/lib/echarts';\nimport Scene from 'claygl/src/Scene';\nimport ShadowMapPass from 'claygl/src/prePass/ShadowMap';\nimport PerspectiveCamera from 'claygl/src/camera/Perspective';\nimport OrthographicCamera from 'claygl/src/camera/Orthographic';\nimport Matrix4 from 'claygl/src/math/Matrix4';\nimport Vector3 from 'claygl/src/math/Vector3';\nimport Vector2 from 'claygl/src/math/Vector2';\nimport notifier from 'claygl/src/core/mixin/notifier';\nimport EffectCompositor from '../effect/EffectCompositor';\nimport TemporalSuperSampling from '../effect/TemporalSuperSampling';\nimport halton from '../effect/halton';\n/**\n * @constructor\n * @alias module:echarts-gl/core/ViewGL\n * @param {string} [projection='perspective']\n */\n\nfunction ViewGL(projection) {\n projection = projection || 'perspective';\n /**\n * @type {module:echarts-gl/core/LayerGL}\n */\n\n this.layer = null;\n /**\n * @type {clay.Scene}\n */\n\n this.scene = new Scene();\n /**\n * @type {clay.Node}\n */\n\n this.rootNode = this.scene;\n this.viewport = {\n x: 0,\n y: 0,\n width: 0,\n height: 0\n };\n this.setProjection(projection);\n this._compositor = new EffectCompositor();\n this._temporalSS = new TemporalSuperSampling();\n this._shadowMapPass = new ShadowMapPass();\n var pcfKernels = [];\n var off = 0;\n\n for (var i = 0; i < 30; i++) {\n var pcfKernel = [];\n\n for (var k = 0; k < 6; k++) {\n pcfKernel.push(halton(off, 2) * 4.0 - 2.0);\n pcfKernel.push(halton(off, 3) * 4.0 - 2.0);\n off++;\n }\n\n pcfKernels.push(pcfKernel);\n }\n\n this._pcfKernels = pcfKernels;\n this.scene.on('beforerender', function (renderer, scene, camera) {\n if (this.needsTemporalSS()) {\n this._temporalSS.jitterProjection(renderer, camera);\n }\n }, this);\n}\n/**\n * Set camera type of group\n * @param {string} cameraType 'perspective' | 'orthographic'\n */\n\n\nViewGL.prototype.setProjection = function (projection) {\n var oldCamera = this.camera;\n oldCamera && oldCamera.update();\n\n if (projection === 'perspective') {\n if (!(this.camera instanceof PerspectiveCamera)) {\n this.camera = new PerspectiveCamera();\n\n if (oldCamera) {\n this.camera.setLocalTransform(oldCamera.localTransform);\n }\n }\n } else {\n if (!(this.camera instanceof OrthographicCamera)) {\n this.camera = new OrthographicCamera();\n\n if (oldCamera) {\n this.camera.setLocalTransform(oldCamera.localTransform);\n }\n }\n } // PENDING\n\n\n this.camera.near = 0.1;\n this.camera.far = 2000;\n};\n/**\n * Set viewport of group\n * @param {number} x Viewport left bottom x\n * @param {number} y Viewport left bottom y\n * @param {number} width Viewport height\n * @param {number} height Viewport height\n * @param {number} [dpr=1]\n */\n\n\nViewGL.prototype.setViewport = function (x, y, width, height, dpr) {\n if (this.camera instanceof PerspectiveCamera) {\n this.camera.aspect = width / height;\n }\n\n dpr = dpr || 1;\n this.viewport.x = x;\n this.viewport.y = y;\n this.viewport.width = width;\n this.viewport.height = height;\n this.viewport.devicePixelRatio = dpr; // Source and output of compositor use high dpr texture.\n // But the intermediate texture of bloom, dof effects use fixed 1.0 dpr\n\n this._compositor.resize(width * dpr, height * dpr);\n\n this._temporalSS.resize(width * dpr, height * dpr);\n};\n/**\n * If contain screen point x, y\n * @param {number} x offsetX\n * @param {number} y offsetY\n * @return {boolean}\n */\n\n\nViewGL.prototype.containPoint = function (x, y) {\n var viewport = this.viewport;\n var height = this.layer.renderer.getHeight(); // Flip y;\n\n y = height - y;\n return x >= viewport.x && y >= viewport.y && x <= viewport.x + viewport.width && y <= viewport.y + viewport.height;\n};\n/**\n * Cast a ray\n * @param {number} x offsetX\n * @param {number} y offsetY\n * @param {clay.math.Ray} out\n * @return {clay.math.Ray}\n */\n\n\nvar ndc = new Vector2();\n\nViewGL.prototype.castRay = function (x, y, out) {\n var renderer = this.layer.renderer;\n var oldViewport = renderer.viewport;\n renderer.viewport = this.viewport;\n renderer.screenToNDC(x, y, ndc);\n this.camera.castRay(ndc, out);\n renderer.viewport = oldViewport;\n return out;\n};\n/**\n * Prepare and update scene before render\n */\n\n\nViewGL.prototype.prepareRender = function () {\n this.scene.update();\n this.camera.update();\n this.scene.updateLights();\n var renderList = this.scene.updateRenderList(this.camera);\n this._needsSortProgressively = false; // If has any transparent mesh needs sort triangles progressively.\n\n for (var i = 0; i < renderList.transparent.length; i++) {\n var renderable = renderList.transparent[i];\n var geometry = renderable.geometry;\n\n if (geometry.needsSortVerticesProgressively && geometry.needsSortVerticesProgressively()) {\n this._needsSortProgressively = true;\n }\n\n if (geometry.needsSortTrianglesProgressively && geometry.needsSortTrianglesProgressively()) {\n this._needsSortProgressively = true;\n }\n }\n\n this._frame = 0;\n\n this._temporalSS.resetFrame(); // var lights = this.scene.getLights();\n // for (var i = 0; i < lights.length; i++) {\n // if (lights[i].cubemap) {\n // if (this._compositor && this._compositor.isSSREnabled()) {\n // lights[i].invisible = true;\n // }\n // else {\n // lights[i].invisible = false;\n // }\n // }\n // }\n\n};\n\nViewGL.prototype.render = function (renderer, accumulating) {\n this._doRender(renderer, accumulating, this._frame);\n\n this._frame++;\n};\n\nViewGL.prototype.needsAccumulate = function () {\n return this.needsTemporalSS() || this._needsSortProgressively;\n};\n\nViewGL.prototype.needsTemporalSS = function () {\n var enableTemporalSS = this._enableTemporalSS;\n\n if (enableTemporalSS === 'auto') {\n enableTemporalSS = this._enablePostEffect;\n }\n\n return enableTemporalSS;\n};\n\nViewGL.prototype.hasDOF = function () {\n return this._enableDOF;\n};\n\nViewGL.prototype.isAccumulateFinished = function () {\n return this.needsTemporalSS() ? this._temporalSS.isFinished() : this._frame > 30;\n};\n\nViewGL.prototype._doRender = function (renderer, accumulating, accumFrame) {\n var scene = this.scene;\n var camera = this.camera;\n accumFrame = accumFrame || 0;\n\n this._updateTransparent(renderer, scene, camera, accumFrame);\n\n if (!accumulating) {\n this._shadowMapPass.kernelPCF = this._pcfKernels[0]; // Not render shadowmap pass in accumulating frame.\n\n this._shadowMapPass.render(renderer, scene, camera, true);\n }\n\n this._updateShadowPCFKernel(accumFrame); // Shadowmap will set clear color.\n\n\n var bgColor = renderer.clearColor;\n renderer.gl.clearColor(bgColor[0], bgColor[1], bgColor[2], bgColor[3]);\n\n if (this._enablePostEffect) {\n // normal render also needs to be jittered when have edge pass.\n if (this.needsTemporalSS()) {\n this._temporalSS.jitterProjection(renderer, camera);\n }\n\n this._compositor.updateNormal(renderer, scene, camera, this._temporalSS.getFrame());\n } // Always update SSAO to make sure have correct ssaoMap status\n\n\n this._updateSSAO(renderer, scene, camera, this._temporalSS.getFrame());\n\n if (this._enablePostEffect) {\n var frameBuffer = this._compositor.getSourceFrameBuffer();\n\n frameBuffer.bind(renderer);\n renderer.gl.clear(renderer.gl.DEPTH_BUFFER_BIT | renderer.gl.COLOR_BUFFER_BIT);\n renderer.render(scene, camera, true, true);\n frameBuffer.unbind(renderer);\n\n if (this.needsTemporalSS() && accumulating) {\n this._compositor.composite(renderer, scene, camera, this._temporalSS.getSourceFrameBuffer(), this._temporalSS.getFrame());\n\n renderer.setViewport(this.viewport);\n\n this._temporalSS.render(renderer);\n } else {\n renderer.setViewport(this.viewport);\n\n this._compositor.composite(renderer, scene, camera, null, 0);\n }\n } else {\n if (this.needsTemporalSS() && accumulating) {\n var frameBuffer = this._temporalSS.getSourceFrameBuffer();\n\n frameBuffer.bind(renderer);\n renderer.saveClear();\n renderer.clearBit = renderer.gl.DEPTH_BUFFER_BIT | renderer.gl.COLOR_BUFFER_BIT;\n renderer.render(scene, camera, true, true);\n renderer.restoreClear();\n frameBuffer.unbind(renderer);\n renderer.setViewport(this.viewport);\n\n this._temporalSS.render(renderer);\n } else {\n renderer.setViewport(this.viewport);\n renderer.render(scene, camera, true, true);\n }\n } // this._shadowMapPass.renderDebug(renderer);\n // this._compositor._normalPass.renderDebug(renderer);\n\n};\n\nViewGL.prototype._updateTransparent = function (renderer, scene, camera, frame) {\n var v3 = new Vector3();\n var invWorldTransform = new Matrix4();\n var cameraWorldPosition = camera.getWorldPosition();\n var transparentList = scene.getRenderList(camera).transparent; // Sort transparent object.\n\n for (var i = 0; i < transparentList.length; i++) {\n var renderable = transparentList[i];\n var geometry = renderable.geometry;\n Matrix4.invert(invWorldTransform, renderable.worldTransform);\n Vector3.transformMat4(v3, cameraWorldPosition, invWorldTransform);\n\n if (geometry.needsSortTriangles && geometry.needsSortTriangles()) {\n geometry.doSortTriangles(v3, frame);\n }\n\n if (geometry.needsSortVertices && geometry.needsSortVertices()) {\n geometry.doSortVertices(v3, frame);\n }\n }\n};\n\nViewGL.prototype._updateSSAO = function (renderer, scene, camera) {\n var ifEnableSSAO = this._enableSSAO && this._enablePostEffect;\n\n if (ifEnableSSAO) {\n this._compositor.updateSSAO(renderer, scene, camera, this._temporalSS.getFrame());\n }\n\n var renderList = scene.getRenderList(camera);\n\n for (var i = 0; i < renderList.opaque.length; i++) {\n var renderable = renderList.opaque[i]; // PENDING\n\n if (renderable.renderNormal) {\n renderable.material[ifEnableSSAO ? 'enableTexture' : 'disableTexture']('ssaoMap');\n }\n\n if (ifEnableSSAO) {\n renderable.material.set('ssaoMap', this._compositor.getSSAOTexture());\n }\n }\n};\n\nViewGL.prototype._updateShadowPCFKernel = function (frame) {\n var pcfKernel = this._pcfKernels[frame % this._pcfKernels.length];\n var renderList = this.scene.getRenderList(this.camera);\n var opaqueList = renderList.opaque;\n\n for (var i = 0; i < opaqueList.length; i++) {\n if (opaqueList[i].receiveShadow) {\n opaqueList[i].material.set('pcfKernel', pcfKernel);\n opaqueList[i].material.define('fragment', 'PCF_KERNEL_SIZE', pcfKernel.length / 2);\n }\n }\n};\n\nViewGL.prototype.dispose = function (renderer) {\n this._compositor.dispose(renderer.gl);\n\n this._temporalSS.dispose(renderer.gl);\n\n this._shadowMapPass.dispose(renderer);\n};\n/**\n * @param {module:echarts/Model} Post effect model\n */\n\n\nViewGL.prototype.setPostEffect = function (postEffectModel, api) {\n var compositor = this._compositor;\n this._enablePostEffect = postEffectModel.get('enable');\n var bloomModel = postEffectModel.getModel('bloom');\n var edgeModel = postEffectModel.getModel('edge');\n var dofModel = postEffectModel.getModel('DOF', postEffectModel.getModel('depthOfField'));\n var ssaoModel = postEffectModel.getModel('SSAO', postEffectModel.getModel('screenSpaceAmbientOcclusion'));\n var ssrModel = postEffectModel.getModel('SSR', postEffectModel.getModel('screenSpaceReflection'));\n var fxaaModel = postEffectModel.getModel('FXAA');\n var colorCorrModel = postEffectModel.getModel('colorCorrection');\n bloomModel.get('enable') ? compositor.enableBloom() : compositor.disableBloom();\n dofModel.get('enable') ? compositor.enableDOF() : compositor.disableDOF();\n ssrModel.get('enable') ? compositor.enableSSR() : compositor.disableSSR();\n colorCorrModel.get('enable') ? compositor.enableColorCorrection() : compositor.disableColorCorrection();\n edgeModel.get('enable') ? compositor.enableEdge() : compositor.disableEdge();\n fxaaModel.get('enable') ? compositor.enableFXAA() : compositor.disableFXAA();\n this._enableDOF = dofModel.get('enable');\n this._enableSSAO = ssaoModel.get('enable');\n this._enableSSAO ? compositor.enableSSAO() : compositor.disableSSAO();\n compositor.setBloomIntensity(bloomModel.get('intensity'));\n compositor.setEdgeColor(edgeModel.get('color'));\n compositor.setColorLookupTexture(colorCorrModel.get('lookupTexture'), api);\n compositor.setExposure(colorCorrModel.get('exposure'));\n ['radius', 'quality', 'intensity'].forEach(function (name) {\n compositor.setSSAOParameter(name, ssaoModel.get(name));\n });\n ['quality', 'maxRoughness', 'physical'].forEach(function (name) {\n compositor.setSSRParameter(name, ssrModel.get(name));\n });\n ['quality', 'focalDistance', 'focalRange', 'blurRadius', 'fstop'].forEach(function (name) {\n compositor.setDOFParameter(name, dofModel.get(name));\n });\n ['brightness', 'contrast', 'saturation'].forEach(function (name) {\n compositor.setColorCorrection(name, colorCorrModel.get(name));\n });\n};\n\nViewGL.prototype.setDOFFocusOnPoint = function (depth) {\n if (this._enablePostEffect) {\n if (depth > this.camera.far || depth < this.camera.near) {\n return;\n }\n\n this._compositor.setDOFParameter('focalDistance', depth);\n\n return true;\n }\n};\n\nViewGL.prototype.setTemporalSuperSampling = function (temporalSuperSamplingModel) {\n this._enableTemporalSS = temporalSuperSamplingModel.get('enable');\n};\n\nViewGL.prototype.isLinearSpace = function () {\n return this._enablePostEffect;\n};\n\nViewGL.prototype.setRootNode = function (rootNode) {\n if (this.rootNode === rootNode) {\n return;\n }\n\n var children = this.rootNode.children();\n\n for (var i = 0; i < children.length; i++) {\n rootNode.add(children[i]);\n }\n\n if (rootNode !== this.scene) {\n this.scene.add(rootNode);\n }\n\n this.rootNode = rootNode;\n}; // Proxies\n\n\nViewGL.prototype.add = function (node3D) {\n this.rootNode.add(node3D);\n};\n\nViewGL.prototype.remove = function (node3D) {\n this.rootNode.remove(node3D);\n};\n\nViewGL.prototype.removeAll = function (node3D) {\n this.rootNode.removeAll(node3D);\n};\n\nObject.assign(ViewGL.prototype, notifier);\nexport default ViewGL;","import Cartesian3D from './grid3D/Cartesian3D';\nimport Axis3D from './grid3D/Axis3D';\nimport * as echarts from 'echarts/lib/echarts';\nimport { getLayoutRect } from 'echarts/lib/util/layout';\nimport ViewGL from '../core/ViewGL';\nimport retrieve from '../util/retrieve';\n\nfunction resizeCartesian3D(grid3DModel, api) {\n // Use left/top/width/height\n var boxLayoutOption = grid3DModel.getBoxLayoutParams();\n var viewport = getLayoutRect(boxLayoutOption, {\n width: api.getWidth(),\n height: api.getHeight()\n }); // Flip Y\n\n viewport.y = api.getHeight() - viewport.y - viewport.height;\n this.viewGL.setViewport(viewport.x, viewport.y, viewport.width, viewport.height, api.getDevicePixelRatio());\n var boxWidth = grid3DModel.get('boxWidth');\n var boxHeight = grid3DModel.get('boxHeight');\n var boxDepth = grid3DModel.get('boxDepth');\n\n if (process.env.NODE_ENV !== 'production') {\n ['x', 'y', 'z'].forEach(function (dim) {\n if (!this.getAxis(dim)) {\n throw new Error('Grid' + grid3DModel.id + ' don\\'t have ' + dim + 'Axis');\n }\n }, this);\n }\n\n this.getAxis('x').setExtent(-boxWidth / 2, boxWidth / 2); // From near to far\n\n this.getAxis('y').setExtent(boxDepth / 2, -boxDepth / 2);\n this.getAxis('z').setExtent(-boxHeight / 2, boxHeight / 2);\n this.size = [boxWidth, boxHeight, boxDepth];\n}\n\nfunction updateCartesian3D(ecModel, api) {\n var dataExtents = {};\n\n function unionDataExtents(dim, extent) {\n dataExtents[dim] = dataExtents[dim] || [Infinity, -Infinity];\n dataExtents[dim][0] = Math.min(extent[0], dataExtents[dim][0]);\n dataExtents[dim][1] = Math.max(extent[1], dataExtents[dim][1]);\n } // Get data extents for scale.\n\n\n ecModel.eachSeries(function (seriesModel) {\n if (seriesModel.coordinateSystem !== this) {\n return;\n }\n\n var data = seriesModel.getData();\n ['x', 'y', 'z'].forEach(function (coordDim) {\n data.mapDimensionsAll(coordDim, true).forEach(function (dataDim) {\n unionDataExtents(coordDim, data.getDataExtent(dataDim, true));\n });\n });\n }, this);\n ['xAxis3D', 'yAxis3D', 'zAxis3D'].forEach(function (axisType) {\n ecModel.eachComponent(axisType, function (axisModel) {\n var dim = axisType.charAt(0);\n var grid3DModel = axisModel.getReferringComponents('grid3D').models[0];\n var cartesian3D = grid3DModel.coordinateSystem;\n\n if (cartesian3D !== this) {\n return;\n }\n\n var axis = cartesian3D.getAxis(dim);\n\n if (axis) {\n if (process.env.NODE_ENV !== 'production') {\n console.warn('Can\\'t have two %s in one grid3D', axisType);\n }\n\n return;\n }\n\n var scale = echarts.helper.createScale(dataExtents[dim] || [Infinity, -Infinity], axisModel);\n axis = new Axis3D(dim, scale);\n axis.type = axisModel.get('type');\n var isCategory = axis.type === 'category';\n axis.onBand = isCategory && axisModel.get('boundaryGap');\n axis.inverse = axisModel.get('inverse');\n axisModel.axis = axis;\n axis.model = axisModel; // override `echarts/coord/Axis#getLabelModel`\n\n axis.getLabelModel = function () {\n return axisModel.getModel('axisLabel', grid3DModel.getModel('axisLabel'));\n }; // override `echarts/coord/Axis#getTickModel`\n\n\n axis.getTickModel = function () {\n return axisModel.getModel('axisTick', grid3DModel.getModel('axisTick'));\n };\n\n cartesian3D.addAxis(axis);\n }, this);\n }, this);\n this.resize(this.model, api);\n}\n\nvar grid3DCreator = {\n dimensions: Cartesian3D.prototype.dimensions,\n create: function (ecModel, api) {\n var cartesian3DList = [];\n ecModel.eachComponent('grid3D', function (grid3DModel) {\n // FIXME\n grid3DModel.__viewGL = grid3DModel.__viewGL || new ViewGL();\n var cartesian3D = new Cartesian3D();\n cartesian3D.model = grid3DModel;\n cartesian3D.viewGL = grid3DModel.__viewGL;\n grid3DModel.coordinateSystem = cartesian3D;\n cartesian3DList.push(cartesian3D); // Inject resize and update\n\n cartesian3D.resize = resizeCartesian3D;\n cartesian3D.update = updateCartesian3D;\n });\n var axesTypes = ['xAxis3D', 'yAxis3D', 'zAxis3D'];\n\n function findAxesModels(seriesModel, ecModel) {\n return axesTypes.map(function (axisType) {\n var axisModel = seriesModel.getReferringComponents(axisType).models[0];\n\n if (axisModel == null) {\n axisModel = ecModel.getComponent(axisType);\n }\n\n if (process.env.NODE_ENV !== 'production') {\n if (!axisModel) {\n throw new Error(axisType + ' \"' + retrieve.firstNotNull(seriesModel.get(axisType + 'Index'), seriesModel.get(axisType + 'Id'), 0) + '\" not found');\n }\n }\n\n return axisModel;\n });\n }\n\n ecModel.eachSeries(function (seriesModel) {\n if (seriesModel.get('coordinateSystem') !== 'cartesian3D') {\n return;\n }\n\n var firstGridModel = seriesModel.getReferringComponents('grid3D').models[0];\n\n if (firstGridModel == null) {\n var axesModels = findAxesModels(seriesModel, ecModel);\n var firstGridModel = axesModels[0].getCoordSysModel();\n axesModels.forEach(function (axisModel) {\n var grid3DModel = axisModel.getCoordSysModel();\n\n if (process.env.NODE_ENV !== 'production') {\n if (!grid3DModel) {\n throw new Error('grid3D \"' + retrieve.firstNotNull(axisModel.get('gridIndex'), axisModel.get('gridId'), 0) + '\" not found');\n }\n\n if (grid3DModel !== firstGridModel) {\n throw new Error('xAxis3D, yAxis3D, zAxis3D must use the same grid');\n }\n }\n });\n }\n\n var coordSys = firstGridModel.coordinateSystem;\n seriesModel.coordinateSystem = coordSys;\n });\n return cartesian3DList;\n }\n};\nexport default grid3DCreator;","import * as echarts from 'echarts/lib/echarts';\nvar Axis3DModel = echarts.ComponentModel.extend({\n type: 'cartesian3DAxis',\n axis: null,\n\n /**\n * @override\n */\n getCoordSysModel: function () {\n return this.ecModel.queryComponents({\n mainType: 'grid3D',\n index: this.option.gridIndex,\n id: this.option.gridId\n })[0];\n }\n});\necharts.helper.mixinAxisModelCommonMethods(Axis3DModel);\nexport default Axis3DModel;","import * as echarts from 'echarts/lib/echarts';\nvar defaultOption = {\n show: true,\n grid3DIndex: 0,\n // 反向坐标轴\n inverse: false,\n // 坐标轴名字\n name: '',\n // 坐标轴名字位置\n nameLocation: 'middle',\n nameTextStyle: {\n fontSize: 16\n },\n // 文字与轴线距离\n nameGap: 20,\n axisPointer: {},\n axisLine: {},\n // 坐标轴小标记\n axisTick: {},\n axisLabel: {},\n // 分隔区域\n splitArea: {}\n};\nvar categoryAxis = echarts.util.merge({\n // 类目起始和结束两端空白策略\n boundaryGap: true,\n // splitArea: {\n // show: false\n // },\n // 坐标轴小标记\n axisTick: {\n // If tick is align with label when boundaryGap is true\n // Default with axisTick\n alignWithLabel: false,\n interval: 'auto'\n },\n // 坐标轴文本标签,详见axis.axisLabel\n axisLabel: {\n interval: 'auto'\n },\n axisPointer: {\n label: {\n show: false\n }\n }\n}, defaultOption);\nvar valueAxis = echarts.util.merge({\n // 数值起始和结束两端空白策略\n boundaryGap: [0, 0],\n // 最小值, 设置成 'dataMin' 则从数据中计算最小值\n // min: null,\n // 最大值,设置成 'dataMax' 则从数据中计算最大值\n // max: null,\n // 脱离0值比例,放大聚焦到最终_min,_max区间\n // scale: false,\n // 分割段数,默认为5\n splitNumber: 5,\n // Minimum interval\n // minInterval: null\n axisPointer: {\n label: {}\n }\n}, defaultOption); // FIXME\n\nvar timeAxis = echarts.util.defaults({\n scale: true,\n min: 'dataMin',\n max: 'dataMax'\n}, valueAxis);\nvar logAxis = echarts.util.defaults({\n logBase: 10\n}, valueAxis);\nlogAxis.scale = true;\nexport default {\n categoryAxis3D: categoryAxis,\n valueAxis3D: valueAxis,\n timeAxis3D: timeAxis,\n logAxis3D: logAxis\n};","import * as echarts from 'echarts/lib/echarts';\nimport axisDefault from './axis3DDefault';\nimport OrdinalMeta from 'echarts/lib/data/OrdinalMeta';\nvar AXIS_TYPES = ['value', 'category', 'time', 'log'];\n/**\n * Generate sub axis model class\n * @param {} registers\n * @param {string} dim 'x' 'y' 'radius' 'angle' 'parallel'\n * @param {module:echarts/model/Component} BaseAxisModelClass\n * @param {Function} axisTypeDefaulter\n * @param {Object} [extraDefaultOption]\n */\n\nexport default function (registers, dim, BaseAxisModelClass, axisTypeDefaulter, extraDefaultOption) {\n AXIS_TYPES.forEach(function (axisType) {\n var AxisModel = BaseAxisModelClass.extend({\n type: dim + 'Axis3D.' + axisType,\n\n /**\n * @type readOnly\n */\n __ordinalMeta: null,\n mergeDefaultAndTheme: function (option, ecModel) {\n var themeModel = ecModel.getTheme();\n echarts.util.merge(option, themeModel.get(axisType + 'Axis3D'));\n echarts.util.merge(option, this.getDefaultOption());\n option.type = axisTypeDefaulter(dim, option);\n },\n\n /**\n * @override\n */\n optionUpdated: function () {\n var thisOption = this.option;\n\n if (thisOption.type === 'category') {\n this.__ordinalMeta = OrdinalMeta.createByAxisModel(this);\n }\n },\n getCategories: function () {\n if (this.option.type === 'category') {\n return this.__ordinalMeta.categories;\n }\n },\n getOrdinalMeta: function () {\n return this.__ordinalMeta;\n },\n defaultOption: echarts.util.merge(echarts.util.clone(axisDefault[axisType + 'Axis3D']), extraDefaultOption || {}, true)\n });\n registers.registerComponentModel(AxisModel);\n }); // TODO\n\n registers.registerSubTypeDefaulter(dim + 'Axis3D', echarts.util.curry(axisTypeDefaulter, dim));\n}\n;","// TODO ECharts GL must be imported whatever component,charts is imported.\nimport '../../echarts-gl';\nimport Grid3DModel from './Grid3DModel';\nimport Grid3DView from './Grid3DView';\nimport grid3DCreator from '../../coord/grid3DCreator';\nimport Axis3DModel from './Axis3DModel';\nimport createAxis3DModel from './createAxis3DModel';\n\nfunction getAxisType(axisDim, option) {\n // Default axis with data is category axis\n return option.type || (option.data ? 'category' : 'value');\n}\n\nexport function install(registers) {\n registers.registerComponentModel(Grid3DModel);\n registers.registerComponentView(Grid3DView);\n registers.registerCoordinateSystem('grid3D', grid3DCreator);\n ['x', 'y', 'z'].forEach(function (dim) {\n createAxis3DModel(registers, dim, Axis3DModel, getAxisType, {\n name: dim.toUpperCase()\n });\n const AxisView = registers.ComponentView.extend({\n type: dim + 'Axis3D'\n });\n registers.registerComponentView(AxisView);\n });\n registers.registerAction({\n type: 'grid3DChangeCamera',\n event: 'grid3dcamerachanged',\n update: 'series:updateCamera'\n }, function (payload, ecModel) {\n ecModel.eachComponent({\n mainType: 'grid3D',\n query: payload\n }, function (componentModel) {\n componentModel.setView(payload);\n });\n });\n registers.registerAction({\n type: 'grid3DShowAxisPointer',\n event: 'grid3dshowaxispointer',\n update: 'grid3D:showAxisPointer'\n }, function (payload, ecModel) {});\n registers.registerAction({\n type: 'grid3DHideAxisPointer',\n event: 'grid3dhideaxispointer',\n update: 'grid3D:hideAxisPointer'\n }, function (payload, ecModel) {});\n}","import { use } from 'echarts/lib/echarts';\nimport { install } from './grid3D/install';\nuse(install);","export default {\n defaultOption: {\n shading: null,\n realisticMaterial: {\n textureTiling: 1,\n textureOffset: 0,\n detailTexture: null\n },\n lambertMaterial: {\n textureTiling: 1,\n textureOffset: 0,\n detailTexture: null\n },\n colorMaterial: {\n textureTiling: 1,\n textureOffset: 0,\n detailTexture: null\n },\n hatchingMaterial: {\n textureTiling: 1,\n textureOffset: 0,\n paperColor: '#fff'\n }\n }\n};","import * as echarts from 'echarts/lib/echarts';\nexport default {\n getFilledRegions: function (regions, mapData) {\n var regionsArr = (regions || []).slice();\n var geoJson;\n\n if (typeof mapData === 'string') {\n mapData = echarts.getMap(mapData);\n geoJson = mapData && mapData.geoJson;\n } else {\n if (mapData && mapData.features) {\n geoJson = mapData;\n }\n }\n\n if (!geoJson) {\n if (process.env.NODE_ENV !== 'production') {\n console.error('Map ' + mapData + ' not exists. You can download map file on http://echarts.baidu.com/download-map.html');\n\n if (!geoJson.features) {\n console.error('Invalid GeoJSON for map3D');\n }\n }\n\n return [];\n }\n\n var dataNameMap = {};\n var features = geoJson.features;\n\n for (var i = 0; i < regionsArr.length; i++) {\n dataNameMap[regionsArr[i].name] = regionsArr[i];\n }\n\n for (var i = 0; i < features.length; i++) {\n var name = features[i].properties.name;\n\n if (!dataNameMap[name]) {\n regionsArr.push({\n name: name\n });\n }\n }\n\n return regionsArr;\n },\n defaultOption: {\n show: true,\n zlevel: -10,\n // geoJson used by geo3D\n map: '',\n // Layout used for viewport\n left: 0,\n top: 0,\n width: '100%',\n height: '100%',\n boxWidth: 100,\n boxHeight: 10,\n boxDepth: 'auto',\n regionHeight: 3,\n environment: 'auto',\n groundPlane: {\n show: false,\n color: '#aaa'\n },\n shading: 'lambert',\n light: {\n main: {\n alpha: 40,\n beta: 30\n }\n },\n viewControl: {\n alpha: 40,\n beta: 0,\n distance: 100,\n orthographicSize: 60,\n minAlpha: 5,\n minBeta: -80,\n maxBeta: 80\n },\n label: {\n show: false,\n // Distance in 3d space.\n distance: 2,\n textStyle: {\n fontSize: 20,\n color: '#000',\n backgroundColor: 'rgba(255,255,255,0.7)',\n padding: 3,\n borderRadius: 4\n }\n },\n // TODO\n // altitude: {\n // min: 'auto',\n // max: 'auto',\n // height: []\n // },\n // labelLine\n // light\n // postEffect\n // temporalSuperSampling\n itemStyle: {\n color: '#fff',\n borderWidth: 0,\n borderColor: '#333'\n },\n emphasis: {\n itemStyle: {\n // color: '#f94b59'\n color: '#639fc0'\n },\n label: {\n show: true\n }\n }\n }\n};","import * as echarts from 'echarts/lib/echarts';\nimport componentViewControlMixin from '../common/componentViewControlMixin';\nimport componentPostEffectMixin from '../common/componentPostEffectMixin';\nimport componentLightMixin from '../common/componentLightMixin';\nimport componentShadingMixin from '../common/componentShadingMixin';\nimport geo3DModelMixin from '../../coord/geo3D/geo3DModelMixin';\nvar Geo3DModel = echarts.ComponentModel.extend({\n type: 'geo3D',\n layoutMode: 'box',\n coordinateSystem: null,\n optionUpdated: function () {\n var option = this.option;\n option.regions = this.getFilledRegions(option.regions, option.map);\n var dimensions = echarts.helper.createDimensions(option.data || [], {\n coordDimensions: ['value'],\n encodeDefine: this.get('encode'),\n dimensionsDefine: this.get('dimensions')\n });\n var list = new echarts.List(dimensions, this);\n list.initData(option.regions);\n var regionModelMap = {};\n list.each(function (idx) {\n var name = list.getName(idx);\n var itemModel = list.getItemModel(idx);\n regionModelMap[name] = itemModel;\n });\n this._regionModelMap = regionModelMap;\n this._data = list;\n },\n getData: function () {\n return this._data;\n },\n getRegionModel: function (idx) {\n var name = this.getData().getName(idx);\n return this._regionModelMap[name] || new echarts.Model(null, this);\n },\n getRegionPolygonCoords: function (idx) {\n var name = this.getData().getName(idx);\n var region = this.coordinateSystem.getRegion(name);\n return region ? region.geometries : [];\n },\n\n /**\n * Format label\n * @param {string} name Region name\n * @param {string} [status='normal'] 'normal' or 'emphasis'\n * @return {string}\n */\n getFormattedLabel: function (dataIndex, status) {\n var name = this._data.getName(dataIndex);\n\n var regionModel = this.getRegionModel(dataIndex);\n var formatter = regionModel.get(status === 'normal' ? ['label', 'formatter'] : ['emphasis', 'label', 'formatter']);\n\n if (formatter == null) {\n formatter = regionModel.get(['label', 'formatter']);\n }\n\n var params = {\n name: name\n };\n\n if (typeof formatter === 'function') {\n params.status = status;\n return formatter(params);\n } else if (typeof formatter === 'string') {\n var serName = params.seriesName;\n return formatter.replace('{a}', serName != null ? serName : '');\n } else {\n return name;\n }\n },\n defaultOption: {\n // itemStyle: {},\n // height,\n // label: {}\n // realisticMaterial\n regions: []\n }\n});\necharts.util.merge(Geo3DModel.prototype, geo3DModelMixin);\necharts.util.merge(Geo3DModel.prototype, componentViewControlMixin);\necharts.util.merge(Geo3DModel.prototype, componentPostEffectMixin);\necharts.util.merge(Geo3DModel.prototype, componentLightMixin);\necharts.util.merge(Geo3DModel.prototype, componentShadingMixin);\nexport default Geo3DModel;","// https://github.com/mapbox/earcut/blob/master/src/earcut.js\nexport default earcut;\n\nfunction earcut(data, holeIndices, dim) {\n dim = dim || 2;\n var hasHoles = holeIndices && holeIndices.length,\n outerLen = hasHoles ? holeIndices[0] * dim : data.length,\n outerNode = linkedList(data, 0, outerLen, dim, true),\n triangles = [];\n if (!outerNode) return triangles;\n var minX, minY, maxX, maxY, x, y, size;\n if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim); // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox\n\n if (data.length > 80 * dim) {\n minX = maxX = data[0];\n minY = maxY = data[1];\n\n for (var i = dim; i < outerLen; i += dim) {\n x = data[i];\n y = data[i + 1];\n if (x < minX) minX = x;\n if (y < minY) minY = y;\n if (x > maxX) maxX = x;\n if (y > maxY) maxY = y;\n } // minX, minY and size are later used to transform coords into integers for z-order calculation\n\n\n size = Math.max(maxX - minX, maxY - minY);\n }\n\n earcutLinked(outerNode, triangles, dim, minX, minY, size);\n return triangles;\n} // create a circular doubly linked list from polygon points in the specified winding order\n\n\nfunction linkedList(data, start, end, dim, clockwise) {\n var i, last;\n\n if (clockwise === signedArea(data, start, end, dim) > 0) {\n for (i = start; i < end; i += dim) last = insertNode(i, data[i], data[i + 1], last);\n } else {\n for (i = end - dim; i >= start; i -= dim) last = insertNode(i, data[i], data[i + 1], last);\n }\n\n if (last && equals(last, last.next)) {\n removeNode(last);\n last = last.next;\n }\n\n return last;\n} // eliminate colinear or duplicate points\n\n\nfunction filterPoints(start, end) {\n if (!start) return start;\n if (!end) end = start;\n var p = start,\n again;\n\n do {\n again = false;\n\n if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) {\n removeNode(p);\n p = end = p.prev;\n if (p === p.next) return null;\n again = true;\n } else {\n p = p.next;\n }\n } while (again || p !== end);\n\n return end;\n} // main ear slicing loop which triangulates a polygon (given as a linked list)\n\n\nfunction earcutLinked(ear, triangles, dim, minX, minY, size, pass) {\n if (!ear) return; // interlink polygon nodes in z-order\n\n if (!pass && size) indexCurve(ear, minX, minY, size);\n var stop = ear,\n prev,\n next; // iterate through ears, slicing them one by one\n\n while (ear.prev !== ear.next) {\n prev = ear.prev;\n next = ear.next;\n\n if (size ? isEarHashed(ear, minX, minY, size) : isEar(ear)) {\n // cut off the triangle\n triangles.push(prev.i / dim);\n triangles.push(ear.i / dim);\n triangles.push(next.i / dim);\n removeNode(ear); // skipping the next vertice leads to less sliver triangles\n\n ear = next.next;\n stop = next.next;\n continue;\n }\n\n ear = next; // if we looped through the whole remaining polygon and can't find any more ears\n\n if (ear === stop) {\n // try filtering points and slicing again\n if (!pass) {\n earcutLinked(filterPoints(ear), triangles, dim, minX, minY, size, 1); // if this didn't work, try curing all small self-intersections locally\n } else if (pass === 1) {\n ear = cureLocalIntersections(ear, triangles, dim);\n earcutLinked(ear, triangles, dim, minX, minY, size, 2); // as a last resort, try splitting the remaining polygon into two\n } else if (pass === 2) {\n splitEarcut(ear, triangles, dim, minX, minY, size);\n }\n\n break;\n }\n }\n} // check whether a polygon node forms a valid ear with adjacent nodes\n\n\nfunction isEar(ear) {\n var a = ear.prev,\n b = ear,\n c = ear.next;\n if (area(a, b, c) >= 0) return false; // reflex, can't be an ear\n // now make sure we don't have other points inside the potential ear\n\n var p = ear.next.next;\n\n while (p !== ear.prev) {\n if (pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;\n p = p.next;\n }\n\n return true;\n}\n\nfunction isEarHashed(ear, minX, minY, size) {\n var a = ear.prev,\n b = ear,\n c = ear.next;\n if (area(a, b, c) >= 0) return false; // reflex, can't be an ear\n // triangle bbox; min & max are calculated like this for speed\n\n var minTX = a.x < b.x ? a.x < c.x ? a.x : c.x : b.x < c.x ? b.x : c.x,\n minTY = a.y < b.y ? a.y < c.y ? a.y : c.y : b.y < c.y ? b.y : c.y,\n maxTX = a.x > b.x ? a.x > c.x ? a.x : c.x : b.x > c.x ? b.x : c.x,\n maxTY = a.y > b.y ? a.y > c.y ? a.y : c.y : b.y > c.y ? b.y : c.y; // z-order range for the current triangle bbox;\n\n var minZ = zOrder(minTX, minTY, minX, minY, size),\n maxZ = zOrder(maxTX, maxTY, minX, minY, size); // first look for points inside the triangle in increasing z-order\n\n var p = ear.nextZ;\n\n while (p && p.z <= maxZ) {\n if (p !== ear.prev && p !== ear.next && pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;\n p = p.nextZ;\n } // then look for points in decreasing z-order\n\n\n p = ear.prevZ;\n\n while (p && p.z >= minZ) {\n if (p !== ear.prev && p !== ear.next && pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;\n p = p.prevZ;\n }\n\n return true;\n} // go through all polygon nodes and cure small local self-intersections\n\n\nfunction cureLocalIntersections(start, triangles, dim) {\n var p = start;\n\n do {\n var a = p.prev,\n b = p.next.next;\n\n if (!equals(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) {\n triangles.push(a.i / dim);\n triangles.push(p.i / dim);\n triangles.push(b.i / dim); // remove two nodes involved\n\n removeNode(p);\n removeNode(p.next);\n p = start = b;\n }\n\n p = p.next;\n } while (p !== start);\n\n return p;\n} // try splitting polygon into two and triangulate them independently\n\n\nfunction splitEarcut(start, triangles, dim, minX, minY, size) {\n // look for a valid diagonal that divides the polygon into two\n var a = start;\n\n do {\n var b = a.next.next;\n\n while (b !== a.prev) {\n if (a.i !== b.i && isValidDiagonal(a, b)) {\n // split the polygon in two by the diagonal\n var c = splitPolygon(a, b); // filter colinear points around the cuts\n\n a = filterPoints(a, a.next);\n c = filterPoints(c, c.next); // run earcut on each half\n\n earcutLinked(a, triangles, dim, minX, minY, size);\n earcutLinked(c, triangles, dim, minX, minY, size);\n return;\n }\n\n b = b.next;\n }\n\n a = a.next;\n } while (a !== start);\n} // link every hole into the outer loop, producing a single-ring polygon without holes\n\n\nfunction eliminateHoles(data, holeIndices, outerNode, dim) {\n var queue = [],\n i,\n len,\n start,\n end,\n list;\n\n for (i = 0, len = holeIndices.length; i < len; i++) {\n start = holeIndices[i] * dim;\n end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;\n list = linkedList(data, start, end, dim, false);\n if (list === list.next) list.steiner = true;\n queue.push(getLeftmost(list));\n }\n\n queue.sort(compareX); // process holes from left to right\n\n for (i = 0; i < queue.length; i++) {\n eliminateHole(queue[i], outerNode);\n outerNode = filterPoints(outerNode, outerNode.next);\n }\n\n return outerNode;\n}\n\nfunction compareX(a, b) {\n return a.x - b.x;\n} // find a bridge between vertices that connects hole with an outer ring and and link it\n\n\nfunction eliminateHole(hole, outerNode) {\n outerNode = findHoleBridge(hole, outerNode);\n\n if (outerNode) {\n var b = splitPolygon(outerNode, hole);\n filterPoints(b, b.next);\n }\n} // David Eberly's algorithm for finding a bridge between hole and outer polygon\n\n\nfunction findHoleBridge(hole, outerNode) {\n var p = outerNode,\n hx = hole.x,\n hy = hole.y,\n qx = -Infinity,\n m; // find a segment intersected by a ray from the hole's leftmost point to the left;\n // segment's endpoint with lesser x will be potential connection point\n\n do {\n if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) {\n var x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y);\n\n if (x <= hx && x > qx) {\n qx = x;\n\n if (x === hx) {\n if (hy === p.y) return p;\n if (hy === p.next.y) return p.next;\n }\n\n m = p.x < p.next.x ? p : p.next;\n }\n }\n\n p = p.next;\n } while (p !== outerNode);\n\n if (!m) return null;\n if (hx === qx) return m.prev; // hole touches outer segment; pick lower endpoint\n // look for points inside the triangle of hole point, segment intersection and endpoint;\n // if there are no points found, we have a valid connection;\n // otherwise choose the point of the minimum angle with the ray as connection point\n\n var stop = m,\n mx = m.x,\n my = m.y,\n tanMin = Infinity,\n tan;\n p = m.next;\n\n while (p !== stop) {\n if (hx >= p.x && p.x >= mx && hx !== p.x && pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)) {\n tan = Math.abs(hy - p.y) / (hx - p.x); // tangential\n\n if ((tan < tanMin || tan === tanMin && p.x > m.x) && locallyInside(p, hole)) {\n m = p;\n tanMin = tan;\n }\n }\n\n p = p.next;\n }\n\n return m;\n} // interlink polygon nodes in z-order\n\n\nfunction indexCurve(start, minX, minY, size) {\n var p = start;\n\n do {\n if (p.z === null) p.z = zOrder(p.x, p.y, minX, minY, size);\n p.prevZ = p.prev;\n p.nextZ = p.next;\n p = p.next;\n } while (p !== start);\n\n p.prevZ.nextZ = null;\n p.prevZ = null;\n sortLinked(p);\n} // Simon Tatham's linked list merge sort algorithm\n// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html\n\n\nfunction sortLinked(list) {\n var i,\n p,\n q,\n e,\n tail,\n numMerges,\n pSize,\n qSize,\n inSize = 1;\n\n do {\n p = list;\n list = null;\n tail = null;\n numMerges = 0;\n\n while (p) {\n numMerges++;\n q = p;\n pSize = 0;\n\n for (i = 0; i < inSize; i++) {\n pSize++;\n q = q.nextZ;\n if (!q) break;\n }\n\n qSize = inSize;\n\n while (pSize > 0 || qSize > 0 && q) {\n if (pSize !== 0 && (qSize === 0 || !q || p.z <= q.z)) {\n e = p;\n p = p.nextZ;\n pSize--;\n } else {\n e = q;\n q = q.nextZ;\n qSize--;\n }\n\n if (tail) tail.nextZ = e;else list = e;\n e.prevZ = tail;\n tail = e;\n }\n\n p = q;\n }\n\n tail.nextZ = null;\n inSize *= 2;\n } while (numMerges > 1);\n\n return list;\n} // z-order of a point given coords and size of the data bounding box\n\n\nfunction zOrder(x, y, minX, minY, size) {\n // coords are transformed into non-negative 15-bit integer range\n x = 32767 * (x - minX) / size;\n y = 32767 * (y - minY) / size;\n x = (x | x << 8) & 0x00FF00FF;\n x = (x | x << 4) & 0x0F0F0F0F;\n x = (x | x << 2) & 0x33333333;\n x = (x | x << 1) & 0x55555555;\n y = (y | y << 8) & 0x00FF00FF;\n y = (y | y << 4) & 0x0F0F0F0F;\n y = (y | y << 2) & 0x33333333;\n y = (y | y << 1) & 0x55555555;\n return x | y << 1;\n} // find the leftmost node of a polygon ring\n\n\nfunction getLeftmost(start) {\n var p = start,\n leftmost = start;\n\n do {\n if (p.x < leftmost.x) leftmost = p;\n p = p.next;\n } while (p !== start);\n\n return leftmost;\n} // check if a point lies within a convex triangle\n\n\nfunction pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {\n return (cx - px) * (ay - py) - (ax - px) * (cy - py) >= 0 && (ax - px) * (by - py) - (bx - px) * (ay - py) >= 0 && (bx - px) * (cy - py) - (cx - px) * (by - py) >= 0;\n} // check if a diagonal between two polygon nodes is valid (lies in polygon interior)\n\n\nfunction isValidDiagonal(a, b) {\n return a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) && locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b);\n} // signed area of a triangle\n\n\nfunction area(p, q, r) {\n return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);\n} // check if two points are equal\n\n\nfunction equals(p1, p2) {\n return p1.x === p2.x && p1.y === p2.y;\n} // check if two segments intersect\n\n\nfunction intersects(p1, q1, p2, q2) {\n if (equals(p1, q1) && equals(p2, q2) || equals(p1, q2) && equals(p2, q1)) return true;\n return area(p1, q1, p2) > 0 !== area(p1, q1, q2) > 0 && area(p2, q2, p1) > 0 !== area(p2, q2, q1) > 0;\n} // check if a polygon diagonal intersects any polygon segments\n\n\nfunction intersectsPolygon(a, b) {\n var p = a;\n\n do {\n if (p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i && intersects(p, p.next, a, b)) return true;\n p = p.next;\n } while (p !== a);\n\n return false;\n} // check if a polygon diagonal is locally inside the polygon\n\n\nfunction locallyInside(a, b) {\n return area(a.prev, a, a.next) < 0 ? area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0 : area(a, b, a.prev) < 0 || area(a, a.next, b) < 0;\n} // check if the middle point of a polygon diagonal is inside the polygon\n\n\nfunction middleInside(a, b) {\n var p = a,\n inside = false,\n px = (a.x + b.x) / 2,\n py = (a.y + b.y) / 2;\n\n do {\n if (p.y > py !== p.next.y > py && p.next.y !== p.y && px < (p.next.x - p.x) * (py - p.y) / (p.next.y - p.y) + p.x) inside = !inside;\n p = p.next;\n } while (p !== a);\n\n return inside;\n} // link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two;\n// if one belongs to the outer ring and another to a hole, it merges it into a single ring\n\n\nfunction splitPolygon(a, b) {\n var a2 = new Node(a.i, a.x, a.y),\n b2 = new Node(b.i, b.x, b.y),\n an = a.next,\n bp = b.prev;\n a.next = b;\n b.prev = a;\n a2.next = an;\n an.prev = a2;\n b2.next = a2;\n a2.prev = b2;\n bp.next = b2;\n b2.prev = bp;\n return b2;\n} // create a node and optionally link it with previous one (in a circular doubly linked list)\n\n\nfunction insertNode(i, x, y, last) {\n var p = new Node(i, x, y);\n\n if (!last) {\n p.prev = p;\n p.next = p;\n } else {\n p.next = last.next;\n p.prev = last;\n last.next.prev = p;\n last.next = p;\n }\n\n return p;\n}\n\nfunction removeNode(p) {\n p.next.prev = p.prev;\n p.prev.next = p.next;\n if (p.prevZ) p.prevZ.nextZ = p.nextZ;\n if (p.nextZ) p.nextZ.prevZ = p.prevZ;\n}\n\nfunction Node(i, x, y) {\n // vertice index in coordinates array\n this.i = i; // vertex coordinates\n\n this.x = x;\n this.y = y; // previous and next vertice nodes in a polygon ring\n\n this.prev = null;\n this.next = null; // z-order curve value\n\n this.z = null; // previous and next nodes in z-order\n\n this.prevZ = null;\n this.nextZ = null; // indicates whether this is a steiner point\n\n this.steiner = false;\n} // return a percentage difference between the polygon area and its triangulation area;\n// used to verify correctness of triangulation\n\n\nearcut.deviation = function (data, holeIndices, dim, triangles) {\n var hasHoles = holeIndices && holeIndices.length;\n var outerLen = hasHoles ? holeIndices[0] * dim : data.length;\n var polygonArea = Math.abs(signedArea(data, 0, outerLen, dim));\n\n if (hasHoles) {\n for (var i = 0, len = holeIndices.length; i < len; i++) {\n var start = holeIndices[i] * dim;\n var end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;\n polygonArea -= Math.abs(signedArea(data, start, end, dim));\n }\n }\n\n var trianglesArea = 0;\n\n for (i = 0; i < triangles.length; i += 3) {\n var a = triangles[i] * dim;\n var b = triangles[i + 1] * dim;\n var c = triangles[i + 2] * dim;\n trianglesArea += Math.abs((data[a] - data[c]) * (data[b + 1] - data[a + 1]) - (data[a] - data[b]) * (data[c + 1] - data[a + 1]));\n }\n\n return polygonArea === 0 && trianglesArea === 0 ? 0 : Math.abs((trianglesArea - polygonArea) / polygonArea);\n};\n\nfunction signedArea(data, start, end, dim) {\n var sum = 0;\n\n for (var i = start, j = end - dim; i < end; i += dim) {\n sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]);\n j = i;\n }\n\n return sum;\n}","function swap(arr, a, b) {\n var tmp = arr[a];\n arr[a] = arr[b];\n arr[b] = tmp;\n}\n\nfunction partition(arr, pivot, left, right, compare) {\n var storeIndex = left;\n var pivotValue = arr[pivot]; // put the pivot on the right\n\n swap(arr, pivot, right); // go through the rest\n\n for (var v = left; v < right; v++) {\n if (compare(arr[v], pivotValue) < 0) {\n swap(arr, v, storeIndex);\n storeIndex++;\n }\n } // finally put the pivot in the correct place\n\n\n swap(arr, right, storeIndex);\n return storeIndex;\n}\n\nfunction quickSort(array, compare, left, right) {\n if (left < right) {\n var pivot = Math.floor((left + right) / 2);\n var newPivot = partition(array, pivot, left, right, compare);\n quickSort(array, compare, left, newPivot - 1);\n quickSort(array, compare, newPivot + 1, right);\n }\n} // TODO Test.\n\n\nfunction ProgressiveQuickSort() {\n // this._pivotList = new LinkedList();\n this._parts = [];\n}\n\nProgressiveQuickSort.prototype.step = function (arr, compare, frame) {\n var len = arr.length;\n\n if (frame === 0) {\n this._parts = [];\n this._sorted = false; // Pick a start pivot;\n\n var pivot = Math.floor(len / 2);\n\n this._parts.push({\n pivot: pivot,\n left: 0,\n right: len - 1\n });\n\n this._currentSortPartIdx = 0;\n }\n\n if (this._sorted) {\n return;\n }\n\n var parts = this._parts;\n\n if (parts.length === 0) {\n this._sorted = true; // Already finished.\n\n return true;\n } else if (parts.length < 512) {\n // Sort large parts in about 10 frames.\n for (var i = 0; i < parts.length; i++) {\n // Partition and Modify the pivot index.\n parts[i].pivot = partition(arr, parts[i].pivot, parts[i].left, parts[i].right, compare);\n }\n\n var subdividedParts = [];\n\n for (var i = 0; i < parts.length; i++) {\n // Subdivide left\n var left = parts[i].left;\n var right = parts[i].pivot - 1;\n\n if (right > left) {\n subdividedParts.push({\n pivot: Math.floor((right + left) / 2),\n left: left,\n right: right\n });\n } // Subdivide right\n\n\n var left = parts[i].pivot + 1;\n var right = parts[i].right;\n\n if (right > left) {\n subdividedParts.push({\n pivot: Math.floor((right + left) / 2),\n left: left,\n right: right\n });\n }\n }\n\n parts = this._parts = subdividedParts;\n } else {\n // console.time('sort');\n // Finally quick sort each parts in 10 frames.\n for (var i = 0; i < Math.floor(parts.length / 10); i++) {\n // Sort near parts first.\n var idx = parts.length - 1 - this._currentSortPartIdx;\n quickSort(arr, compare, parts[idx].left, parts[idx].right);\n this._currentSortPartIdx++; // Finish sort\n\n if (this._currentSortPartIdx === parts.length) {\n this._sorted = true;\n return true;\n }\n } // console.timeEnd('sort');\n\n }\n\n return false;\n};\n\nProgressiveQuickSort.sort = quickSort;\nexport default ProgressiveQuickSort;","import ProgressiveQuickSort from '../ProgressiveQuickSort';\nimport glmatrix from 'claygl/src/dep/glmatrix';\nvar vec3 = glmatrix.vec3;\nvar p0 = vec3.create();\nvar p1 = vec3.create();\nvar p2 = vec3.create(); // var cp = vec3.create();\n\nexport default {\n needsSortTriangles: function () {\n return this.indices && this.sortTriangles;\n },\n needsSortTrianglesProgressively: function () {\n return this.needsSortTriangles() && this.triangleCount >= 2e4;\n },\n doSortTriangles: function (cameraPos, frame) {\n var indices = this.indices; // Do progressive quick sort.\n\n if (frame === 0) {\n var posAttr = this.attributes.position;\n var cameraPos = cameraPos.array;\n\n if (!this._triangleZList || this._triangleZList.length !== this.triangleCount) {\n this._triangleZList = new Float32Array(this.triangleCount);\n this._sortedTriangleIndices = new Uint32Array(this.triangleCount);\n this._indicesTmp = new indices.constructor(indices.length);\n this._triangleZListTmp = new Float32Array(this.triangleCount);\n }\n\n var cursor = 0;\n var firstZ;\n\n for (var i = 0; i < indices.length;) {\n posAttr.get(indices[i++], p0);\n posAttr.get(indices[i++], p1);\n posAttr.get(indices[i++], p2); // FIXME If use center ?\n // cp[0] = (p0[0] + p1[0] + p2[0]) / 3;\n // cp[1] = (p0[1] + p1[1] + p2[1]) / 3;\n // cp[2] = (p0[2] + p1[2] + p2[2]) / 3;\n // Camera position is in object space\n // Use max of three points, PENDING\n\n var z0 = vec3.sqrDist(p0, cameraPos);\n var z1 = vec3.sqrDist(p1, cameraPos);\n var z2 = vec3.sqrDist(p2, cameraPos);\n var zMax = Math.min(z0, z1);\n zMax = Math.min(zMax, z2);\n\n if (i === 3) {\n firstZ = zMax;\n zMax = 0;\n } else {\n // Only store the difference to avoid the precision issue.\n zMax = zMax - firstZ;\n }\n\n this._triangleZList[cursor++] = zMax;\n }\n }\n\n var sortedTriangleIndices = this._sortedTriangleIndices;\n\n for (var i = 0; i < sortedTriangleIndices.length; i++) {\n sortedTriangleIndices[i] = i;\n }\n\n if (this.triangleCount < 2e4) {\n // Use simple timsort for simple geometries.\n if (frame === 0) {\n // Use native sort temporary.\n this._simpleSort(true);\n }\n } else {\n for (var i = 0; i < 3; i++) {\n this._progressiveQuickSort(frame * 3 + i);\n }\n }\n\n var targetIndices = this._indicesTmp;\n var targetTriangleZList = this._triangleZListTmp;\n var faceZList = this._triangleZList;\n\n for (var i = 0; i < this.triangleCount; i++) {\n var fromIdx3 = sortedTriangleIndices[i] * 3;\n var toIdx3 = i * 3;\n targetIndices[toIdx3++] = indices[fromIdx3++];\n targetIndices[toIdx3++] = indices[fromIdx3++];\n targetIndices[toIdx3] = indices[fromIdx3];\n targetTriangleZList[i] = faceZList[sortedTriangleIndices[i]];\n } // Swap indices.\n\n\n var tmp = this._indicesTmp;\n this._indicesTmp = this.indices;\n this.indices = tmp;\n var tmp = this._triangleZListTmp;\n this._triangleZListTmp = this._triangleZList;\n this._triangleZList = tmp;\n this.dirtyIndices();\n },\n _simpleSort: function (useNativeQuickSort) {\n var faceZList = this._triangleZList;\n var sortedTriangleIndices = this._sortedTriangleIndices;\n\n function compare(a, b) {\n // Sort from far to near. which is descending order\n return faceZList[b] - faceZList[a];\n }\n\n if (useNativeQuickSort) {\n Array.prototype.sort.call(sortedTriangleIndices, compare);\n } else {\n ProgressiveQuickSort.sort(sortedTriangleIndices, compare, 0, sortedTriangleIndices.length - 1);\n }\n },\n _progressiveQuickSort: function (frame) {\n var faceZList = this._triangleZList;\n var sortedTriangleIndices = this._sortedTriangleIndices;\n this._quickSort = this._quickSort || new ProgressiveQuickSort();\n\n this._quickSort.step(sortedTriangleIndices, function (a, b) {\n return faceZList[b] - faceZList[a];\n }, frame);\n }\n};","export function getVisualColor(data) {\n const style = data.getVisual('style');\n\n if (style) {\n const drawType = data.getVisual('drawType');\n return style[drawType];\n }\n}\nexport function getVisualOpacity(data) {\n const style = data.getVisual('style');\n return style.opacity;\n}\nexport function getItemVisualColor(data, idx) {\n const style = data.getItemVisual(idx, 'style');\n\n if (style) {\n const drawType = data.getVisual('drawType');\n return style[drawType];\n }\n}\nexport function getItemVisualOpacity(data, idx) {\n const style = data.getItemVisual(idx, 'style');\n return style && style.opacity;\n}","import * as echarts from 'echarts/lib/echarts';\nimport ZRTextureAtlasSurface from '../../util/ZRTextureAtlasSurface';\nimport LabelsMesh from '../../util/mesh/LabelsMesh';\nimport retrieve from '../../util/retrieve';\nimport { getItemVisualColor, getItemVisualOpacity } from '../../util/visual';\nimport { createTextStyle } from 'echarts/lib/label/labelStyle';\nvar LABEL_NORMAL_SHOW_BIT = 1;\nvar LABEL_EMPHASIS_SHOW_BIT = 2;\n\nfunction LabelsBuilder(width, height, api) {\n this._labelsMesh = new LabelsMesh();\n this._labelTextureSurface = new ZRTextureAtlasSurface({\n width: 512,\n height: 512,\n devicePixelRatio: api.getDevicePixelRatio(),\n onupdate: function () {\n api.getZr().refresh();\n }\n });\n this._api = api;\n\n this._labelsMesh.material.set('textureAtlas', this._labelTextureSurface.getTexture());\n}\n\nLabelsBuilder.prototype.getLabelPosition = function (dataIndex, positionDesc, distance) {\n return [0, 0, 0];\n};\n\nLabelsBuilder.prototype.getLabelDistance = function (dataIndex, positionDesc, distance) {\n return 0;\n};\n\nLabelsBuilder.prototype.getMesh = function () {\n return this._labelsMesh;\n};\n\nLabelsBuilder.prototype.updateData = function (data, start, end) {\n if (start == null) {\n start = 0;\n }\n\n if (end == null) {\n end = data.count();\n }\n\n if (!this._labelsVisibilitiesBits || this._labelsVisibilitiesBits.length !== end - start) {\n this._labelsVisibilitiesBits = new Uint8Array(end - start);\n }\n\n var normalLabelVisibilityQuery = ['label', 'show'];\n var emphasisLabelVisibilityQuery = ['emphasis', 'label', 'show'];\n\n for (var idx = start; idx < end; idx++) {\n var itemModel = data.getItemModel(idx);\n var normalVisibility = itemModel.get(normalLabelVisibilityQuery);\n var emphasisVisibility = itemModel.get(emphasisLabelVisibilityQuery);\n\n if (emphasisVisibility == null) {\n emphasisVisibility = normalVisibility;\n }\n\n var bit = (normalVisibility ? LABEL_NORMAL_SHOW_BIT : 0) | (emphasisVisibility ? LABEL_EMPHASIS_SHOW_BIT : 0);\n this._labelsVisibilitiesBits[idx - start] = bit;\n }\n\n this._start = start;\n this._end = end;\n this._data = data;\n};\n\nLabelsBuilder.prototype.updateLabels = function (highlightDataIndices) {\n if (!this._data) {\n return;\n }\n\n highlightDataIndices = highlightDataIndices || [];\n var hasHighlightData = highlightDataIndices.length > 0;\n var highlightDataIndicesMap = {};\n\n for (var i = 0; i < highlightDataIndices.length; i++) {\n highlightDataIndicesMap[highlightDataIndices[i]] = true;\n }\n\n this._labelsMesh.geometry.convertToDynamicArray(true);\n\n this._labelTextureSurface.clear();\n\n var normalLabelQuery = ['label'];\n var emphasisLabelQuery = ['emphasis', 'label'];\n var seriesModel = this._data.hostModel;\n var data = this._data;\n var seriesLabelModel = seriesModel.getModel(normalLabelQuery);\n var seriesLabelEmphasisModel = seriesModel.getModel(emphasisLabelQuery, seriesLabelModel);\n var textAlignMap = {\n left: 'right',\n right: 'left',\n top: 'center',\n bottom: 'center'\n };\n var textVerticalAlignMap = {\n left: 'middle',\n right: 'middle',\n top: 'bottom',\n bottom: 'top'\n };\n\n for (var dataIndex = this._start; dataIndex < this._end; dataIndex++) {\n var isEmphasis = false;\n\n if (hasHighlightData && highlightDataIndicesMap[dataIndex]) {\n isEmphasis = true;\n }\n\n var ifShow = this._labelsVisibilitiesBits[dataIndex - this._start] & (isEmphasis ? LABEL_EMPHASIS_SHOW_BIT : LABEL_NORMAL_SHOW_BIT);\n\n if (!ifShow) {\n continue;\n }\n\n var itemModel = data.getItemModel(dataIndex);\n var labelModel = itemModel.getModel(isEmphasis ? emphasisLabelQuery : normalLabelQuery, isEmphasis ? seriesLabelEmphasisModel : seriesLabelModel);\n var distance = labelModel.get('distance') || 0;\n var position = labelModel.get('position');\n\n var dpr = this._api.getDevicePixelRatio();\n\n var text = seriesModel.getFormattedLabel(dataIndex, isEmphasis ? 'emphasis' : 'normal');\n\n if (text == null || text === '') {\n return;\n } // TODO Background.\n\n\n var textEl = new echarts.graphic.Text({\n style: createTextStyle(labelModel, {\n text: text,\n fill: labelModel.get('color') || getItemVisualColor(data, dataIndex) || '#000',\n align: 'left',\n verticalAlign: 'top',\n opacity: retrieve.firstNotNull(labelModel.get('opacity'), getItemVisualOpacity(data, dataIndex), 1)\n })\n });\n var rect = textEl.getBoundingRect();\n var lineHeight = 1.2;\n rect.height *= lineHeight;\n\n var coords = this._labelTextureSurface.add(textEl);\n\n var textAlign = textAlignMap[position] || 'center';\n var textVerticalAlign = textVerticalAlignMap[position] || 'bottom';\n\n this._labelsMesh.geometry.addSprite(this.getLabelPosition(dataIndex, position, distance), [rect.width * dpr, rect.height * dpr], coords, textAlign, textVerticalAlign, this.getLabelDistance(dataIndex, position, distance) * dpr);\n }\n\n this._labelsMesh.material.set('uvScale', this._labelTextureSurface.getCoordsScale()); // var canvas = this._labelTextureSurface.getTexture().image;\n // document.body.appendChild(canvas);\n // canvas.style.cssText = 'position:absolute;z-index: 1000';\n // Update image.\n\n\n this._labelTextureSurface.getZr().refreshImmediately();\n\n this._labelsMesh.geometry.convertToTypedArray();\n\n this._labelsMesh.geometry.dirty();\n};\n\nLabelsBuilder.prototype.dispose = function () {\n this._labelTextureSurface.dispose();\n};\n\nexport default LabelsBuilder;","import * as echarts from 'echarts/lib/echarts';\nimport graphicGL from '../../util/graphicGL';\nimport earcut from '../../util/earcut';\nimport LinesGeo from '../../util/geometry/Lines3D';\nimport retrieve from '../../util/retrieve';\nimport glmatrix from 'claygl/src/dep/glmatrix';\nimport trianglesSortMixin from '../../util/geometry/trianglesSortMixin';\nimport LabelsBuilder from './LabelsBuilder';\nimport lines3DGLSL from '../../util/shader/lines3D.glsl.js';\nimport { getItemVisualColor, getItemVisualOpacity } from '../../util/visual';\nvar vec3 = glmatrix.vec3;\ngraphicGL.Shader.import(lines3DGLSL);\n\nfunction Geo3DBuilder(api) {\n this.rootNode = new graphicGL.Node(); // Cache triangulation result\n\n this._triangulationResults = {};\n this._shadersMap = graphicGL.COMMON_SHADERS.filter(function (shaderName) {\n return shaderName !== 'shadow';\n }).reduce(function (obj, shaderName) {\n obj[shaderName] = graphicGL.createShader('ecgl.' + shaderName);\n return obj;\n }, {});\n this._linesShader = graphicGL.createShader('ecgl.meshLines3D');\n var groundMaterials = {};\n graphicGL.COMMON_SHADERS.forEach(function (shading) {\n groundMaterials[shading] = new graphicGL.Material({\n shader: graphicGL.createShader('ecgl.' + shading)\n });\n });\n this._groundMaterials = groundMaterials;\n this._groundMesh = new graphicGL.Mesh({\n geometry: new graphicGL.PlaneGeometry({\n dynamic: true\n }),\n castShadow: false,\n renderNormal: true,\n $ignorePicking: true\n });\n\n this._groundMesh.rotation.rotateX(-Math.PI / 2);\n\n this._labelsBuilder = new LabelsBuilder(512, 512, api); // Give a large render order.\n\n this._labelsBuilder.getMesh().renderOrder = 100;\n this._labelsBuilder.getMesh().material.depthTest = false;\n this.rootNode.add(this._labelsBuilder.getMesh());\n\n this._initMeshes();\n\n this._api = api;\n}\n\nGeo3DBuilder.prototype = {\n constructor: Geo3DBuilder,\n // Which dimension to extrude. Y or Z\n extrudeY: true,\n update: function (componentModel, ecModel, api, start, end) {\n var data = componentModel.getData();\n\n if (start == null) {\n start = 0;\n }\n\n if (end == null) {\n end = data.count();\n }\n\n this._startIndex = start;\n this._endIndex = end - 1;\n\n this._triangulation(componentModel, start, end);\n\n var shader = this._getShader(componentModel.get('shading'));\n\n this._prepareMesh(componentModel, shader, api, start, end);\n\n this.rootNode.updateWorldTransform();\n\n this._updateRegionMesh(componentModel, api, start, end);\n\n var coordSys = componentModel.coordinateSystem; // PENDING\n\n if (coordSys.type === 'geo3D') {\n this._updateGroundPlane(componentModel, coordSys, api);\n }\n\n var self = this;\n\n this._labelsBuilder.updateData(data, start, end);\n\n this._labelsBuilder.getLabelPosition = function (dataIndex, positionDesc, distance) {\n var name = data.getName(dataIndex);\n var center;\n var height = distance;\n\n if (coordSys.type === 'geo3D') {\n var region = coordSys.getRegion(name);\n\n if (!region) {\n return [NaN, NaN, NaN];\n }\n\n center = region.getCenter();\n var pos = coordSys.dataToPoint([center[0], center[1], height]);\n return pos;\n } else {\n var tmp = self._triangulationResults[dataIndex - self._startIndex];\n var center = self.extrudeY ? [(tmp.max[0] + tmp.min[0]) / 2, tmp.max[1] + height, (tmp.max[2] + tmp.min[2]) / 2] : [(tmp.max[0] + tmp.min[0]) / 2, (tmp.max[1] + tmp.min[1]) / 2, tmp.max[2] + height];\n }\n };\n\n this._data = data;\n\n this._labelsBuilder.updateLabels();\n\n this._updateDebugWireframe(componentModel); // Reset some state.\n\n\n this._lastHoverDataIndex = 0;\n },\n _initMeshes: function () {\n var self = this;\n\n function createPolygonMesh() {\n var mesh = new graphicGL.Mesh({\n name: 'Polygon',\n material: new graphicGL.Material({\n shader: self._shadersMap.lambert\n }),\n geometry: new graphicGL.Geometry({\n sortTriangles: true,\n dynamic: true\n }),\n // TODO Disable culling\n culling: false,\n ignorePicking: true,\n // Render normal in normal pass\n renderNormal: true\n });\n Object.assign(mesh.geometry, trianglesSortMixin);\n return mesh;\n }\n\n var polygonMesh = createPolygonMesh();\n var linesMesh = new graphicGL.Mesh({\n material: new graphicGL.Material({\n shader: this._linesShader\n }),\n castShadow: false,\n ignorePicking: true,\n $ignorePicking: true,\n geometry: new LinesGeo({\n useNativeLine: false\n })\n });\n this.rootNode.add(polygonMesh);\n this.rootNode.add(linesMesh);\n polygonMesh.material.define('both', 'VERTEX_COLOR');\n polygonMesh.material.define('fragment', 'DOUBLE_SIDED');\n this._polygonMesh = polygonMesh;\n this._linesMesh = linesMesh;\n this.rootNode.add(this._groundMesh);\n },\n _getShader: function (shading) {\n var shader = this._shadersMap[shading];\n\n if (!shader) {\n if (process.env.NODE_ENV !== 'production') {\n console.warn('Unkown shading ' + shading);\n } // Default use lambert shader.\n\n\n shader = this._shadersMap.lambert;\n }\n\n shader.__shading = shading;\n return shader;\n },\n _prepareMesh: function (componentModel, shader, api, start, end) {\n var polygonVertexCount = 0;\n var polygonTriangleCount = 0;\n var linesVertexCount = 0;\n var linesTriangleCount = 0; // TODO Lines\n\n for (var idx = start; idx < end; idx++) {\n var polyInfo = this._getRegionPolygonInfo(idx);\n\n var lineInfo = this._getRegionLinesInfo(idx, componentModel, this._linesMesh.geometry);\n\n polygonVertexCount += polyInfo.vertexCount;\n polygonTriangleCount += polyInfo.triangleCount;\n linesVertexCount += lineInfo.vertexCount;\n linesTriangleCount += lineInfo.triangleCount;\n }\n\n var polygonMesh = this._polygonMesh;\n var polygonGeo = polygonMesh.geometry;\n ['position', 'normal', 'texcoord0', 'color'].forEach(function (attrName) {\n polygonGeo.attributes[attrName].init(polygonVertexCount);\n });\n polygonGeo.indices = polygonVertexCount > 0xffff ? new Uint32Array(polygonTriangleCount * 3) : new Uint16Array(polygonTriangleCount * 3);\n\n if (polygonMesh.material.shader !== shader) {\n polygonMesh.material.attachShader(shader, true);\n }\n\n graphicGL.setMaterialFromModel(shader.__shading, polygonMesh.material, componentModel, api);\n\n if (linesVertexCount > 0) {\n this._linesMesh.geometry.resetOffset();\n\n this._linesMesh.geometry.setVertexCount(linesVertexCount);\n\n this._linesMesh.geometry.setTriangleCount(linesTriangleCount);\n } // Indexing data index from vertex index.\n\n\n this._dataIndexOfVertex = new Uint32Array(polygonVertexCount); // Indexing vertex index range from data index\n\n this._vertexRangeOfDataIndex = new Uint32Array((end - start) * 2);\n },\n _updateRegionMesh: function (componentModel, api, start, end) {\n var data = componentModel.getData();\n var vertexOffset = 0;\n var triangleOffset = 0; // Materials configurations.\n\n var hasTranparentRegion = false;\n var polygonMesh = this._polygonMesh;\n var linesMesh = this._linesMesh;\n\n for (var dataIndex = start; dataIndex < end; dataIndex++) {\n // Get bunch of visual properties.\n var regionModel = componentModel.getRegionModel(dataIndex);\n var itemStyleModel = regionModel.getModel('itemStyle');\n var color = retrieve.firstNotNull(getItemVisualColor(data, dataIndex), itemStyleModel.get('color'), '#fff');\n var opacity = retrieve.firstNotNull(getItemVisualOpacity(data, dataIndex), itemStyleModel.get('opacity'), 1);\n var colorArr = graphicGL.parseColor(color);\n var borderColorArr = graphicGL.parseColor(itemStyleModel.get('borderColor'));\n colorArr[3] *= opacity;\n borderColorArr[3] *= opacity;\n var isTransparent = colorArr[3] < 0.99;\n polygonMesh.material.set('color', [1, 1, 1, 1]);\n hasTranparentRegion = hasTranparentRegion || isTransparent;\n var regionHeight = retrieve.firstNotNull(regionModel.get('height', true), componentModel.get('regionHeight'));\n\n var newOffsets = this._updatePolygonGeometry(componentModel, polygonMesh.geometry, dataIndex, regionHeight, vertexOffset, triangleOffset, colorArr);\n\n for (var i = vertexOffset; i < newOffsets.vertexOffset; i++) {\n this._dataIndexOfVertex[i] = dataIndex;\n }\n\n this._vertexRangeOfDataIndex[(dataIndex - start) * 2] = vertexOffset;\n this._vertexRangeOfDataIndex[(dataIndex - start) * 2 + 1] = newOffsets.vertexOffset;\n vertexOffset = newOffsets.vertexOffset;\n triangleOffset = newOffsets.triangleOffset; // Update lines.\n\n var lineWidth = itemStyleModel.get('borderWidth');\n var hasLine = lineWidth > 0;\n\n if (hasLine) {\n lineWidth *= api.getDevicePixelRatio();\n\n this._updateLinesGeometry(linesMesh.geometry, componentModel, dataIndex, regionHeight, lineWidth, componentModel.coordinateSystem.transform);\n }\n\n linesMesh.invisible = !hasLine;\n linesMesh.material.set({\n color: borderColorArr\n });\n }\n\n var polygonMesh = this._polygonMesh;\n polygonMesh.material.transparent = hasTranparentRegion;\n polygonMesh.material.depthMask = !hasTranparentRegion;\n polygonMesh.geometry.updateBoundingBox();\n polygonMesh.frontFace = this.extrudeY ? graphicGL.Mesh.CCW : graphicGL.Mesh.CW; // Update tangents\n\n if (polygonMesh.material.get('normalMap')) {\n polygonMesh.geometry.generateTangents();\n }\n\n polygonMesh.seriesIndex = componentModel.seriesIndex;\n polygonMesh.on('mousemove', this._onmousemove, this);\n polygonMesh.on('mouseout', this._onmouseout, this);\n },\n _updateDebugWireframe: function (componentModel) {\n var debugWireframeModel = componentModel.getModel('debug.wireframe'); // TODO Unshow\n\n if (debugWireframeModel.get('show')) {\n var color = graphicGL.parseColor(debugWireframeModel.get('lineStyle.color') || 'rgba(0,0,0,0.5)');\n var width = retrieve.firstNotNull(debugWireframeModel.get('lineStyle.width'), 1); // TODO Will cause highlight wrong\n\n var mesh = this._polygonMesh;\n mesh.geometry.generateBarycentric();\n mesh.material.define('both', 'WIREFRAME_TRIANGLE');\n mesh.material.set('wireframeLineColor', color);\n mesh.material.set('wireframeLineWidth', width);\n }\n },\n _onmousemove: function (e) {\n var dataIndex = this._dataIndexOfVertex[e.triangle[0]];\n\n if (dataIndex == null) {\n dataIndex = -1;\n }\n\n if (dataIndex !== this._lastHoverDataIndex) {\n this.downplay(this._lastHoverDataIndex);\n this.highlight(dataIndex);\n\n this._labelsBuilder.updateLabels([dataIndex]);\n }\n\n this._lastHoverDataIndex = dataIndex;\n this._polygonMesh.dataIndex = dataIndex;\n },\n _onmouseout: function (e) {\n if (e.target) {\n this.downplay(this._lastHoverDataIndex);\n this._lastHoverDataIndex = -1;\n this._polygonMesh.dataIndex = -1;\n }\n\n this._labelsBuilder.updateLabels([]);\n },\n _updateGroundPlane: function (componentModel, geo3D, api) {\n var groundModel = componentModel.getModel('groundPlane', componentModel);\n this._groundMesh.invisible = !groundModel.get('show', true);\n\n if (this._groundMesh.invisible) {\n return;\n }\n\n var shading = componentModel.get('shading');\n var material = this._groundMaterials[shading];\n\n if (!material) {\n if (process.env.NODE_ENV !== 'production') {\n console.warn('Unkown shading ' + shading);\n }\n\n material = this._groundMaterials.lambert;\n }\n\n graphicGL.setMaterialFromModel(shading, material, groundModel, api);\n\n if (material.get('normalMap')) {\n this._groundMesh.geometry.generateTangents();\n }\n\n this._groundMesh.material = material;\n\n this._groundMesh.material.set('color', graphicGL.parseColor(groundModel.get('color')));\n\n this._groundMesh.scale.set(geo3D.size[0], geo3D.size[2], 1);\n },\n _triangulation: function (componentModel, start, end) {\n this._triangulationResults = [];\n var minAll = [Infinity, Infinity, Infinity];\n var maxAll = [-Infinity, -Infinity, -Infinity];\n var coordSys = componentModel.coordinateSystem;\n\n for (var idx = start; idx < end; idx++) {\n var polygons = [];\n var polygonCoords = componentModel.getRegionPolygonCoords(idx);\n\n for (var i = 0; i < polygonCoords.length; i++) {\n var exterior = polygonCoords[i].exterior;\n var interiors = polygonCoords[i].interiors;\n var points = [];\n var holes = [];\n\n if (exterior.length < 3) {\n continue;\n }\n\n var offset = 0;\n\n for (var j = 0; j < exterior.length; j++) {\n var p = exterior[j];\n points[offset++] = p[0];\n points[offset++] = p[1];\n }\n\n for (var j = 0; j < interiors.length; j++) {\n if (interiors[j].length < 3) {\n continue;\n }\n\n var startIdx = points.length / 2;\n\n for (var k = 0; k < interiors[j].length; k++) {\n var p = interiors[j][k];\n points.push(p[0]);\n points.push(p[1]);\n }\n\n holes.push(startIdx);\n }\n\n var triangles = earcut(points, holes);\n var points3 = new Float64Array(points.length / 2 * 3);\n var pos = [];\n var min = [Infinity, Infinity, Infinity];\n var max = [-Infinity, -Infinity, -Infinity];\n var off3 = 0;\n\n for (var j = 0; j < points.length;) {\n vec3.set(pos, points[j++], 0, points[j++]);\n\n if (coordSys && coordSys.transform) {\n vec3.transformMat4(pos, pos, coordSys.transform);\n }\n\n vec3.min(min, min, pos);\n vec3.max(max, max, pos);\n points3[off3++] = pos[0];\n points3[off3++] = pos[1];\n points3[off3++] = pos[2];\n }\n\n vec3.min(minAll, minAll, min);\n vec3.max(maxAll, maxAll, max);\n polygons.push({\n points: points3,\n indices: triangles,\n min: min,\n max: max\n });\n }\n\n this._triangulationResults.push(polygons);\n }\n\n this._geoBoundingBox = [minAll, maxAll];\n },\n\n /**\n * Get region vertex and triangle count\n */\n _getRegionPolygonInfo: function (idx) {\n var polygons = this._triangulationResults[idx - this._startIndex];\n var sideVertexCount = 0;\n var sideTriangleCount = 0;\n\n for (var i = 0; i < polygons.length; i++) {\n sideVertexCount += polygons[i].points.length / 3;\n sideTriangleCount += polygons[i].indices.length / 3;\n }\n\n var vertexCount = sideVertexCount * 2 + sideVertexCount * 4;\n var triangleCount = sideTriangleCount * 2 + sideVertexCount * 2;\n return {\n vertexCount: vertexCount,\n triangleCount: triangleCount\n };\n },\n _updatePolygonGeometry: function (componentModel, geometry, dataIndex, regionHeight, vertexOffset, triangleOffset, color) {\n // FIXME\n var projectUVOnGround = componentModel.get('projectUVOnGround');\n var positionAttr = geometry.attributes.position;\n var normalAttr = geometry.attributes.normal;\n var texcoordAttr = geometry.attributes.texcoord0;\n var colorAttr = geometry.attributes.color;\n var polygons = this._triangulationResults[dataIndex - this._startIndex];\n var hasColor = colorAttr.value && color;\n var indices = geometry.indices;\n var extrudeCoordIndex = this.extrudeY ? 1 : 2;\n var sideCoordIndex = this.extrudeY ? 2 : 1;\n var scale = [this.rootNode.worldTransform.x.len(), this.rootNode.worldTransform.y.len(), this.rootNode.worldTransform.z.len()];\n var min = vec3.mul([], this._geoBoundingBox[0], scale);\n var max = vec3.mul([], this._geoBoundingBox[1], scale);\n var maxDimSize = Math.max(max[0] - min[0], max[2] - min[2]);\n\n function addVertices(polygon, y, insideOffset) {\n var points = polygon.points;\n var pointsLen = points.length;\n var currentPosition = [];\n var uv = [];\n\n for (var k = 0; k < pointsLen; k += 3) {\n currentPosition[0] = points[k];\n currentPosition[extrudeCoordIndex] = y;\n currentPosition[sideCoordIndex] = points[k + 2];\n uv[0] = (points[k] * scale[0] - min[0]) / maxDimSize;\n uv[1] = (points[k + 2] * scale[sideCoordIndex] - min[2]) / maxDimSize;\n positionAttr.set(vertexOffset, currentPosition);\n\n if (hasColor) {\n colorAttr.set(vertexOffset, color);\n }\n\n texcoordAttr.set(vertexOffset++, uv);\n }\n }\n\n function buildTopBottom(polygon, y, insideOffset) {\n var startVertexOffset = vertexOffset;\n addVertices(polygon, y, insideOffset);\n var len = polygon.indices.length;\n\n for (var k = 0; k < len; k++) {\n indices[triangleOffset * 3 + k] = polygon.indices[k] + startVertexOffset;\n }\n\n triangleOffset += polygon.indices.length / 3;\n }\n\n var normalTop = this.extrudeY ? [0, 1, 0] : [0, 0, 1];\n var normalBottom = vec3.negate([], normalTop);\n\n for (var p = 0; p < polygons.length; p++) {\n var startVertexOffset = vertexOffset;\n var polygon = polygons[p]; // BOTTOM\n\n buildTopBottom(polygon, 0, 0); // TOP\n\n buildTopBottom(polygon, regionHeight, 0);\n var ringVertexCount = polygon.points.length / 3;\n\n for (var v = 0; v < ringVertexCount; v++) {\n normalAttr.set(startVertexOffset + v, normalBottom);\n normalAttr.set(startVertexOffset + v + ringVertexCount, normalTop);\n }\n\n var quadToTriangle = [0, 3, 1, 1, 3, 2];\n var quadPos = [[], [], [], []];\n var a = [];\n var b = [];\n var normal = [];\n var uv = [];\n var len = 0;\n\n for (var v = 0; v < ringVertexCount; v++) {\n var next = (v + 1) % ringVertexCount;\n var dx = (polygon.points[next * 3] - polygon.points[v * 3]) * scale[0];\n var dy = (polygon.points[next * 3 + 2] - polygon.points[v * 3 + 2]) * scale[sideCoordIndex];\n var sideLen = Math.sqrt(dx * dx + dy * dy); // 0----1\n // 3----2\n\n for (var k = 0; k < 4; k++) {\n var isCurrent = k === 0 || k === 3;\n var idx3 = (isCurrent ? v : next) * 3;\n quadPos[k][0] = polygon.points[idx3];\n quadPos[k][extrudeCoordIndex] = k > 1 ? regionHeight : 0;\n quadPos[k][sideCoordIndex] = polygon.points[idx3 + 2];\n positionAttr.set(vertexOffset + k, quadPos[k]);\n\n if (projectUVOnGround) {\n uv[0] = (polygon.points[idx3] * scale[0] - min[0]) / maxDimSize;\n uv[1] = (polygon.points[idx3 + 2] * scale[sideCoordIndex] - min[sideCoordIndex]) / maxDimSize;\n } else {\n uv[0] = (isCurrent ? len : len + sideLen) / maxDimSize;\n uv[1] = (quadPos[k][extrudeCoordIndex] * scale[extrudeCoordIndex] - min[extrudeCoordIndex]) / maxDimSize;\n }\n\n texcoordAttr.set(vertexOffset + k, uv);\n }\n\n vec3.sub(a, quadPos[1], quadPos[0]);\n vec3.sub(b, quadPos[3], quadPos[0]);\n vec3.cross(normal, a, b);\n vec3.normalize(normal, normal);\n\n for (var k = 0; k < 4; k++) {\n normalAttr.set(vertexOffset + k, normal);\n\n if (hasColor) {\n colorAttr.set(vertexOffset + k, color);\n }\n }\n\n for (var k = 0; k < 6; k++) {\n indices[triangleOffset * 3 + k] = quadToTriangle[k] + vertexOffset;\n }\n\n vertexOffset += 4;\n triangleOffset += 2;\n len += sideLen;\n }\n }\n\n geometry.dirty();\n return {\n vertexOffset: vertexOffset,\n triangleOffset: triangleOffset\n };\n },\n _getRegionLinesInfo: function (idx, componentModel, geometry) {\n var vertexCount = 0;\n var triangleCount = 0;\n var regionModel = componentModel.getRegionModel(idx);\n var itemStyleModel = regionModel.getModel('itemStyle');\n var lineWidth = itemStyleModel.get('borderWidth');\n\n if (lineWidth > 0) {\n var polygonCoords = componentModel.getRegionPolygonCoords(idx);\n polygonCoords.forEach(function (coords) {\n var exterior = coords.exterior;\n var interiors = coords.interiors;\n vertexCount += geometry.getPolylineVertexCount(exterior);\n triangleCount += geometry.getPolylineTriangleCount(exterior);\n\n for (var i = 0; i < interiors.length; i++) {\n vertexCount += geometry.getPolylineVertexCount(interiors[i]);\n triangleCount += geometry.getPolylineTriangleCount(interiors[i]);\n }\n }, this);\n }\n\n return {\n vertexCount: vertexCount,\n triangleCount: triangleCount\n };\n },\n _updateLinesGeometry: function (geometry, componentModel, dataIndex, regionHeight, lineWidth, transform) {\n function convertToPoints3(polygon) {\n var points = new Float64Array(polygon.length * 3);\n var offset = 0;\n var pos = [];\n\n for (var i = 0; i < polygon.length; i++) {\n pos[0] = polygon[i][0]; // Add a offset to avoid z-fighting\n\n pos[1] = regionHeight + 0.1;\n pos[2] = polygon[i][1];\n\n if (transform) {\n vec3.transformMat4(pos, pos, transform);\n }\n\n points[offset++] = pos[0];\n points[offset++] = pos[1];\n points[offset++] = pos[2];\n }\n\n return points;\n }\n\n var whiteColor = [1, 1, 1, 1];\n var coords = componentModel.getRegionPolygonCoords(dataIndex);\n coords.forEach(function (geo) {\n var exterior = geo.exterior;\n var interiors = geo.interiors;\n geometry.addPolyline(convertToPoints3(exterior), whiteColor, lineWidth);\n\n for (var i = 0; i < interiors.length; i++) {\n geometry.addPolyline(convertToPoints3(interiors[i]), whiteColor, lineWidth);\n }\n });\n },\n highlight: function (dataIndex) {\n var data = this._data;\n\n if (!data) {\n return;\n }\n\n var itemModel = data.getItemModel(dataIndex);\n var emphasisItemStyleModel = itemModel.getModel(['emphasis', 'itemStyle']);\n var emphasisColor = emphasisItemStyleModel.get('color');\n var emphasisOpacity = retrieve.firstNotNull(emphasisItemStyleModel.get('opacity'), getItemVisualOpacity(data, dataIndex), 1);\n\n if (emphasisColor == null) {\n var color = getItemVisualColor(data, dataIndex);\n emphasisColor = echarts.color.lift(color, -0.4);\n }\n\n if (emphasisOpacity == null) {\n emphasisOpacity = getItemVisualOpacity(data, dataIndex);\n }\n\n var colorArr = graphicGL.parseColor(emphasisColor);\n colorArr[3] *= emphasisOpacity;\n\n this._setColorOfDataIndex(data, dataIndex, colorArr);\n },\n downplay: function (dataIndex) {\n var data = this._data;\n\n if (!data) {\n return;\n }\n\n var itemStyleModel = data.getItemModel(dataIndex);\n var color = retrieve.firstNotNull(getItemVisualColor(data, dataIndex), itemStyleModel.get(['itemStyle', 'color']), '#fff');\n var opacity = retrieve.firstNotNull(getItemVisualOpacity(data, dataIndex), itemStyleModel.get(['itemStyle', 'opacity']), 1);\n var colorArr = graphicGL.parseColor(color);\n colorArr[3] *= opacity;\n\n this._setColorOfDataIndex(data, dataIndex, colorArr);\n },\n dispose: function () {\n this._labelsBuilder.dispose();\n },\n _setColorOfDataIndex: function (data, dataIndex, colorArr) {\n if (dataIndex < this._startIndex && dataIndex > this._endIndex) {\n return;\n }\n\n dataIndex -= this._startIndex;\n\n for (var i = this._vertexRangeOfDataIndex[dataIndex * 2]; i < this._vertexRangeOfDataIndex[dataIndex * 2 + 1]; i++) {\n this._polygonMesh.geometry.attributes.color.set(i, colorArr);\n }\n\n this._polygonMesh.geometry.dirty();\n\n this._api.getZr().refresh();\n }\n};\nexport default Geo3DBuilder;","import Geo3DBuilder from '../common/Geo3DBuilder';\nimport * as echarts from 'echarts/lib/echarts';\nimport graphicGL from '../../util/graphicGL';\nimport OrbitControl from '../../util/OrbitControl';\nimport SceneHelper from '../common/SceneHelper';\nexport default echarts.ComponentView.extend({\n type: 'geo3D',\n __ecgl__: true,\n init: function (ecModel, api) {\n this._geo3DBuilder = new Geo3DBuilder(api);\n this.groupGL = new graphicGL.Node();\n this._lightRoot = new graphicGL.Node();\n this._sceneHelper = new SceneHelper(this._lightRoot);\n\n this._sceneHelper.initLight(this._lightRoot);\n\n this._control = new OrbitControl({\n zr: api.getZr()\n });\n\n this._control.init();\n },\n render: function (geo3DModel, ecModel, api) {\n this.groupGL.add(this._geo3DBuilder.rootNode);\n var geo3D = geo3DModel.coordinateSystem;\n\n if (!geo3D || !geo3D.viewGL) {\n return;\n } // Always have light.\n\n\n geo3D.viewGL.add(this._lightRoot);\n\n if (geo3DModel.get('show')) {\n geo3D.viewGL.add(this.groupGL);\n } else {\n geo3D.viewGL.remove(this.groupGL);\n }\n\n var control = this._control;\n control.setViewGL(geo3D.viewGL);\n var viewControlModel = geo3DModel.getModel('viewControl');\n control.setFromViewControlModel(viewControlModel, 0);\n\n this._sceneHelper.setScene(geo3D.viewGL.scene);\n\n this._sceneHelper.updateLight(geo3DModel); // Set post effect\n\n\n geo3D.viewGL.setPostEffect(geo3DModel.getModel('postEffect'), api);\n geo3D.viewGL.setTemporalSuperSampling(geo3DModel.getModel('temporalSuperSampling')); // Must update after geo3D.viewGL.setPostEffect\n\n this._geo3DBuilder.update(geo3DModel, ecModel, api, 0, geo3DModel.getData().count());\n\n var srgbDefineMethod = geo3D.viewGL.isLinearSpace() ? 'define' : 'undefine';\n\n this._geo3DBuilder.rootNode.traverse(function (mesh) {\n if (mesh.material) {\n mesh.material[srgbDefineMethod]('fragment', 'SRGB_DECODE');\n }\n });\n\n control.off('update');\n control.on('update', function () {\n api.dispatchAction({\n type: 'geo3DChangeCamera',\n alpha: control.getAlpha(),\n beta: control.getBeta(),\n distance: control.getDistance(),\n center: control.getCenter(),\n from: this.uid,\n geo3DId: geo3DModel.id\n });\n });\n control.update();\n },\n afterRender: function (geo3DModel, ecModel, api, layerGL) {\n var renderer = layerGL.renderer;\n\n this._sceneHelper.updateAmbientCubemap(renderer, geo3DModel, api);\n\n this._sceneHelper.updateSkybox(renderer, geo3DModel, api);\n },\n dispose: function () {\n this._control.dispose();\n\n this._geo3DBuilder.dispose();\n }\n});","\n/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements. See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership. The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License. You may obtain a copy of the License at\n*\n* http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied. See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/\n\n\n/**\n * AUTO-GENERATED FILE. DO NOT MODIFY.\n */\n\n/*\r\n* Licensed to the Apache Software Foundation (ASF) under one\r\n* or more contributor license agreements. See the NOTICE file\r\n* distributed with this work for additional information\r\n* regarding copyright ownership. The ASF licenses this file\r\n* to you under the Apache License, Version 2.0 (the\r\n* \"License\"); you may not use this file except in compliance\r\n* with the License. You may obtain a copy of the License at\r\n*\r\n* http://www.apache.org/licenses/LICENSE-2.0\r\n*\r\n* Unless required by applicable law or agreed to in writing,\r\n* software distributed under the License is distributed on an\r\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\r\n* KIND, either express or implied. See the License for the\r\n* specific language governing permissions and limitations\r\n* under the License.\r\n*/\nvar geoCoordMap = {\n 'Russia': [100, 60],\n 'United States': [-99, 38],\n 'United States of America': [-99, 38]\n};\nexport default function fixGeoCoords(mapType, region) {\n if (mapType === 'world') {\n var geoCoord = geoCoordMap[region.name];\n\n if (geoCoord) {\n var cp = [geoCoord[0], geoCoord[1]];\n region.setCenter(cp);\n }\n }\n}","import * as echarts from 'echarts/lib/echarts';\nimport glmatrix from 'claygl/src/dep/glmatrix';\nvar vec3 = glmatrix.vec3;\nvar mat4 = glmatrix.mat4;\nimport textCoord from 'echarts/lib/coord/geo/fix/textCoord';\nimport geoCoord from 'echarts/lib/coord/geo/fix/geoCoord'; // Geo fix functions\n\nvar geoFixFuncs = [textCoord, geoCoord];\n\nfunction Geo3D(name, map, geoJson, specialAreas, nameMap) {\n this.name = name;\n this.map = map;\n this.regionHeight = 0;\n this.regions = [];\n this._nameCoordMap = {};\n this.loadGeoJson(geoJson, specialAreas, nameMap);\n this.transform = mat4.identity(new Float64Array(16));\n this.invTransform = mat4.identity(new Float64Array(16)); // Which dimension to extrude. Y or Z\n\n this.extrudeY = true;\n this.altitudeAxis;\n}\n\nGeo3D.prototype = {\n constructor: Geo3D,\n type: 'geo3D',\n dimensions: ['lng', 'lat', 'alt'],\n containPoint: function () {},\n loadGeoJson: function (geoJson, specialAreas, nameMap) {\n var parseGeoJSON = echarts.parseGeoJSON || echarts.parseGeoJson;\n\n try {\n this.regions = geoJson ? parseGeoJSON(geoJson) : [];\n } catch (e) {\n throw 'Invalid geoJson format\\n' + e;\n }\n\n specialAreas = specialAreas || {};\n nameMap = nameMap || {};\n var regions = this.regions;\n var regionsMap = {};\n\n for (var i = 0; i < regions.length; i++) {\n var regionName = regions[i].name; // Try use the alias in nameMap\n\n regionName = nameMap[regionName] || regionName;\n regions[i].name = regionName;\n regionsMap[regionName] = regions[i]; // Add geoJson\n\n this.addGeoCoord(regionName, regions[i].getCenter()); // Some area like Alaska in USA map needs to be tansformed\n // to look better\n\n var specialArea = specialAreas[regionName];\n\n if (specialArea) {\n regions[i].transformTo(specialArea.left, specialArea.top, specialArea.width, specialArea.height);\n }\n }\n\n this._regionsMap = regionsMap;\n this._geoRect = null;\n geoFixFuncs.forEach(function (fixFunc) {\n fixFunc(this);\n }, this);\n },\n getGeoBoundingRect: function () {\n if (this._geoRect) {\n return this._geoRect;\n }\n\n var rect;\n var regions = this.regions;\n\n for (var i = 0; i < regions.length; i++) {\n var regionRect = regions[i].getBoundingRect();\n rect = rect || regionRect.clone();\n rect.union(regionRect);\n } // FIXME Always return new ?\n\n\n return this._geoRect = rect || new echarts.graphic.BoundingRect(0, 0, 0, 0);\n },\n\n /**\n * Add geoCoord for indexing by name\n * @param {string} name\n * @param {Array.} geoCoord\n */\n addGeoCoord: function (name, geoCoord) {\n this._nameCoordMap[name] = geoCoord;\n },\n\n /**\n * @param {string} name\n * @return {module:echarts/coord/geo/Region}\n */\n getRegion: function (name) {\n return this._regionsMap[name];\n },\n getRegionByCoord: function (coord) {\n var regions = this.regions;\n\n for (var i = 0; i < regions.length; i++) {\n if (regions[i].contain(coord)) {\n return regions[i];\n }\n }\n },\n setSize: function (width, height, depth) {\n this.size = [width, height, depth];\n var rect = this.getGeoBoundingRect();\n var scaleX = width / rect.width;\n var scaleZ = -depth / rect.height;\n var translateX = -width / 2 - rect.x * scaleX;\n var translateZ = depth / 2 - rect.y * scaleZ;\n var position = this.extrudeY ? [translateX, 0, translateZ] : [translateX, translateZ, 0];\n var scale = this.extrudeY ? [scaleX, 1, scaleZ] : [scaleX, scaleZ, 1];\n var m = this.transform;\n mat4.identity(m);\n mat4.translate(m, m, position);\n mat4.scale(m, m, scale);\n mat4.invert(this.invTransform, m);\n },\n dataToPoint: function (data, out) {\n out = out || [];\n var extrudeCoordIndex = this.extrudeY ? 1 : 2;\n var sideCoordIndex = this.extrudeY ? 2 : 1;\n var altitudeVal = data[2]; // PENDING.\n\n if (isNaN(altitudeVal)) {\n altitudeVal = 0;\n } // lng\n\n\n out[0] = data[0]; // lat\n\n out[sideCoordIndex] = data[1];\n\n if (this.altitudeAxis) {\n out[extrudeCoordIndex] = this.altitudeAxis.dataToCoord(altitudeVal);\n } else {\n out[extrudeCoordIndex] = 0;\n } // PENDING different region height.\n\n\n out[extrudeCoordIndex] += this.regionHeight;\n vec3.transformMat4(out, out, this.transform);\n return out;\n },\n pointToData: function (point, out) {// TODO\n }\n};\nexport default Geo3D;","import Geo3D from './geo3D/Geo3D';\nimport * as echarts from 'echarts/lib/echarts';\nimport { getLayoutRect } from 'echarts/lib/util/layout';\nimport ViewGL from '../core/ViewGL';\nimport retrieve from '../util/retrieve';\n\nfunction resizeGeo3D(geo3DModel, api) {\n // Use left/top/width/height\n var boxLayoutOption = geo3DModel.getBoxLayoutParams();\n var viewport = getLayoutRect(boxLayoutOption, {\n width: api.getWidth(),\n height: api.getHeight()\n }); // Flip Y\n\n viewport.y = api.getHeight() - viewport.y - viewport.height;\n this.viewGL.setViewport(viewport.x, viewport.y, viewport.width, viewport.height, api.getDevicePixelRatio());\n var geoRect = this.getGeoBoundingRect();\n var aspect = geoRect.width / geoRect.height * (geo3DModel.get('aspectScale') || 0.75);\n var width = geo3DModel.get('boxWidth');\n var depth = geo3DModel.get('boxDepth');\n var height = geo3DModel.get('boxHeight');\n\n if (height == null) {\n height = 5;\n }\n\n if (isNaN(width) && isNaN(depth)) {\n // Default to have 100 width\n width = 100;\n }\n\n if (isNaN(depth)) {\n depth = width / aspect;\n } else if (isNaN(width)) {\n width = depth / aspect;\n }\n\n this.setSize(width, height, depth);\n this.regionHeight = geo3DModel.get('regionHeight');\n\n if (this.altitudeAxis) {\n this.altitudeAxis.setExtent(0, Math.max(height - this.regionHeight, 0));\n }\n}\n\nfunction updateGeo3D(ecModel, api) {\n var altitudeDataExtent = [Infinity, -Infinity];\n ecModel.eachSeries(function (seriesModel) {\n if (seriesModel.coordinateSystem !== this) {\n return;\n }\n\n if (seriesModel.type === 'series.map3D') {\n return;\n } // Get altitude data extent.\n\n\n var data = seriesModel.getData();\n var altDims = seriesModel.coordDimToDataDim('alt');\n var altDim = altDims && altDims[0];\n\n if (altDim) {\n // TODO altitiude is in coords of lines.\n var dataExtent = data.getDataExtent(altDim, true);\n altitudeDataExtent[0] = Math.min(altitudeDataExtent[0], dataExtent[0]);\n altitudeDataExtent[1] = Math.max(altitudeDataExtent[1], dataExtent[1]);\n }\n }, this); // Create altitude axis\n\n if (altitudeDataExtent && isFinite(altitudeDataExtent[1] - altitudeDataExtent[0])) {\n var scale = echarts.helper.createScale(altitudeDataExtent, {\n type: 'value',\n // PENDING\n min: 'dataMin',\n max: 'dataMax'\n });\n this.altitudeAxis = new echarts.Axis('altitude', scale); // Resize again\n\n this.resize(this.model, api);\n }\n}\n\nif (process.env.NODE_ENV !== 'production') {\n var mapNotExistsError = function (name) {\n console.error('Map ' + name + ' not exists. You can download map file on http://echarts.baidu.com/download-map.html');\n };\n}\n\nvar idStart = 0;\nvar geo3DCreator = {\n dimensions: Geo3D.prototype.dimensions,\n create: function (ecModel, api) {\n var geo3DList = [];\n\n if (!echarts.getMap) {\n throw new Error('geo3D component depends on geo component');\n }\n\n function createGeo3D(componentModel, idx) {\n var geo3D = geo3DCreator.createGeo3D(componentModel); // FIXME\n\n componentModel.__viewGL = componentModel.__viewGL || new ViewGL();\n geo3D.viewGL = componentModel.__viewGL;\n componentModel.coordinateSystem = geo3D;\n geo3D.model = componentModel;\n geo3DList.push(geo3D); // Inject resize\n\n geo3D.resize = resizeGeo3D;\n geo3D.resize(componentModel, api);\n geo3D.update = updateGeo3D;\n }\n\n ecModel.eachComponent('geo3D', function (geo3DModel, idx) {\n createGeo3D(geo3DModel, idx);\n });\n ecModel.eachSeriesByType('map3D', function (map3DModel, idx) {\n var coordSys = map3DModel.get('coordinateSystem');\n\n if (coordSys == null) {\n coordSys = 'geo3D';\n }\n\n if (coordSys === 'geo3D') {\n createGeo3D(map3DModel, idx);\n }\n });\n ecModel.eachSeries(function (seriesModel) {\n if (seriesModel.get('coordinateSystem') === 'geo3D') {\n if (seriesModel.type === 'series.map3D') {\n return;\n }\n\n var geo3DModel = seriesModel.getReferringComponents('geo3D').models[0];\n\n if (!geo3DModel) {\n geo3DModel = ecModel.getComponent('geo3D');\n }\n\n if (!geo3DModel) {\n throw new Error('geo \"' + retrieve.firstNotNull(seriesModel.get('geo3DIndex'), seriesModel.get('geo3DId'), 0) + '\" not found');\n }\n\n seriesModel.coordinateSystem = geo3DModel.coordinateSystem;\n }\n });\n return geo3DList;\n },\n createGeo3D: function (componentModel) {\n var mapData = componentModel.get('map');\n var name;\n\n if (typeof mapData === 'string') {\n name = mapData;\n mapData = echarts.getMap(mapData);\n } else {\n if (mapData && mapData.features) {\n mapData = {\n geoJson: mapData\n };\n }\n }\n\n if (process.env.NODE_ENV !== 'production') {\n if (!mapData) {\n mapNotExistsError(mapData);\n }\n\n if (!mapData.geoJson.features) {\n throw new Error('Invalid GeoJSON for map3D');\n }\n }\n\n if (name == null) {\n name = 'GEO_ANONYMOUS_' + idStart++;\n }\n\n return new Geo3D(name + idStart++, name, mapData && mapData.geoJson, mapData && mapData.specialAreas, componentModel.get('nameMap'));\n }\n};\nexport default geo3DCreator;","// TODO ECharts GL must be imported whatever component,charts is imported.\nimport '../../echarts-gl';\nimport Geo3DModel from './Geo3DModel';\nimport Geo3DView from './Geo3DView';\nimport geo3DCreator from '../../coord/geo3DCreator';\nexport function install(registers) {\n registers.registerComponentModel(Geo3DModel);\n registers.registerComponentView(Geo3DView);\n registers.registerAction({\n type: 'geo3DChangeCamera',\n event: 'geo3dcamerachanged',\n update: 'series:updateCamera'\n }, function (payload, ecModel) {\n ecModel.eachComponent({\n mainType: 'geo3D',\n query: payload\n }, function (componentModel) {\n componentModel.setView(payload);\n });\n });\n registers.registerCoordinateSystem('geo3D', geo3DCreator);\n}","import * as echarts from 'echarts/lib/echarts';\nimport componentViewControlMixin from '../common/componentViewControlMixin';\nimport componentPostEffectMixin from '../common/componentPostEffectMixin';\nimport componentLightMixin from '../common/componentLightMixin';\nimport componentShadingMixin from '../common/componentShadingMixin';\n\nfunction defaultId(option, idx) {\n option.id = option.id || option.name || idx + '';\n}\n\nvar GlobeModel = echarts.ComponentModel.extend({\n type: 'globe',\n layoutMode: 'box',\n coordinateSystem: null,\n init: function () {\n GlobeModel.superApply(this, 'init', arguments);\n echarts.util.each(this.option.layers, function (layerOption, idx) {\n echarts.util.merge(layerOption, this.defaultLayerOption);\n defaultId(layerOption, idx);\n }, this);\n },\n mergeOption: function (option) {\n // TODO test\n var oldLayers = this.option.layers;\n this.option.layers = null;\n GlobeModel.superApply(this, 'mergeOption', arguments);\n\n function createLayerMap(layers) {\n return echarts.util.reduce(layers, function (obj, layerOption, idx) {\n defaultId(layerOption, idx);\n obj[layerOption.id] = layerOption;\n return obj;\n }, {});\n }\n\n if (oldLayers && oldLayers.length) {\n var newLayerMap = createLayerMap(option.layers);\n var oldLayerMap = createLayerMap(oldLayers);\n\n for (var id in newLayerMap) {\n if (oldLayerMap[id]) {\n echarts.util.merge(oldLayerMap[id], newLayerMap[id], true);\n } else {\n oldLayers.push(option.layers[id]);\n }\n } // Copy back\n\n\n this.option.layers = oldLayers;\n } // else overwrite\n // Set default\n\n\n echarts.util.each(this.option.layers, function (layerOption) {\n echarts.util.merge(layerOption, this.defaultLayerOption);\n }, this);\n },\n optionUpdated: function () {\n this.updateDisplacementHash();\n },\n defaultLayerOption: {\n show: true,\n type: 'overlay'\n },\n defaultOption: {\n show: true,\n zlevel: -10,\n // Layout used for viewport\n left: 0,\n top: 0,\n width: '100%',\n height: '100%',\n environment: 'auto',\n baseColor: '#fff',\n // Base albedo texture\n baseTexture: '',\n // Height texture for bump mapping and vertex displacement\n heightTexture: '',\n // Texture for vertex displacement, default use heightTexture\n displacementTexture: '',\n // Scale of vertex displacement, available only if displacementTexture is set.\n displacementScale: 0,\n // Detail of displacement. 'low', 'medium', 'high', 'ultra'\n displacementQuality: 'medium',\n // Globe radius\n globeRadius: 100,\n // Globe outer radius. Which is max of altitude.\n globeOuterRadius: 150,\n // Shading of globe\n shading: 'lambert',\n // Extend light\n light: {\n // Main sun light\n main: {\n // Time, default it will use system time\n time: ''\n }\n },\n // atmosphere\n atmosphere: {\n show: false,\n offset: 5,\n color: '#ffffff',\n glowPower: 6.0,\n innerGlowPower: 2.0\n },\n // light\n // postEffect\n // temporalSuperSampling\n viewControl: {\n autoRotate: true,\n panSensitivity: 0,\n targetCoord: null\n },\n // {\n // show: true,\n // name: 'cloud',\n // type: 'overlay',\n // shading: 'lambert',\n // distance: 10,\n // texture: ''\n // }\n // {\n // type: 'blend',\n // blendTo: 'albedo'\n // blendType: 'source-over'\n // }\n layers: []\n },\n setDisplacementData: function (data, width, height) {\n this.displacementData = data;\n this.displacementWidth = width;\n this.displacementHeight = height;\n },\n getDisplacementTexture: function () {\n return this.get('displacementTexture') || this.get('heightTexture');\n },\n getDisplacemenScale: function () {\n var displacementTexture = this.getDisplacementTexture();\n var displacementScale = this.get('displacementScale');\n\n if (!displacementTexture || displacementTexture === 'none') {\n displacementScale = 0;\n }\n\n return displacementScale;\n },\n hasDisplacement: function () {\n return this.getDisplacemenScale() > 0;\n },\n _displacementChanged: true,\n _displacementScale: 0,\n updateDisplacementHash: function () {\n var displacementTexture = this.getDisplacementTexture();\n var displacementScale = this.getDisplacemenScale();\n this._displacementChanged = this._displacementTexture !== displacementTexture || this._displacementScale !== displacementScale;\n this._displacementTexture = displacementTexture;\n this._displacementScale = displacementScale;\n },\n isDisplacementChanged: function () {\n return this._displacementChanged;\n }\n});\necharts.util.merge(GlobeModel.prototype, componentViewControlMixin);\necharts.util.merge(GlobeModel.prototype, componentPostEffectMixin);\necharts.util.merge(GlobeModel.prototype, componentLightMixin);\necharts.util.merge(GlobeModel.prototype, componentShadingMixin);\nexport default GlobeModel;","import { use } from 'echarts/lib/echarts';\nimport { install } from './geo3D/install';\nuse(install);","/*\n (c) 2011-2014, Vladimir Agafonkin\n SunCalc is a JavaScript library for calculating sun/mooon position and light phases.\n https://github.com/mourner/suncalc\n*/\n// shortcuts for easier to read formulas\nvar PI = Math.PI,\n sin = Math.sin,\n cos = Math.cos,\n tan = Math.tan,\n asin = Math.asin,\n atan = Math.atan2,\n rad = PI / 180; // sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas\n// date/time constants and conversions\n\nvar dayMs = 1000 * 60 * 60 * 24,\n J1970 = 2440588,\n J2000 = 2451545;\n\nfunction toJulian(date) {\n return date.valueOf() / dayMs - 0.5 + J1970;\n}\n\nfunction toDays(date) {\n return toJulian(date) - J2000;\n} // general calculations for position\n\n\nvar e = rad * 23.4397; // obliquity of the Earth\n\nfunction rightAscension(l, b) {\n return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l));\n}\n\nfunction declination(l, b) {\n return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l));\n}\n\nfunction azimuth(H, phi, dec) {\n return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi));\n}\n\nfunction altitude(H, phi, dec) {\n return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H));\n}\n\nfunction siderealTime(d, lw) {\n return rad * (280.16 + 360.9856235 * d) - lw;\n} // general sun calculations\n\n\nfunction solarMeanAnomaly(d) {\n return rad * (357.5291 + 0.98560028 * d);\n}\n\nfunction eclipticLongitude(M) {\n var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)),\n // equation of center\n P = rad * 102.9372; // perihelion of the Earth\n\n return M + C + P + PI;\n}\n\nfunction sunCoords(d) {\n var M = solarMeanAnomaly(d),\n L = eclipticLongitude(M);\n return {\n dec: declination(L, 0),\n ra: rightAscension(L, 0)\n };\n}\n\nvar SunCalc = {}; // calculates sun position for a given date and latitude/longitude\n\nSunCalc.getPosition = function (date, lat, lng) {\n var lw = rad * -lng,\n phi = rad * lat,\n d = toDays(date),\n c = sunCoords(d),\n H = siderealTime(d, lw) - c.ra;\n return {\n azimuth: azimuth(H, phi, c.dec),\n altitude: altitude(H, phi, c.dec)\n };\n};\n\nexport default SunCalc;","export default \"@export ecgl.atmosphere.vertex\\nattribute vec3 position: POSITION;\\nattribute vec3 normal : NORMAL;\\nuniform mat4 worldViewProjection : WORLDVIEWPROJECTION;\\nuniform mat4 normalMatrix : WORLDINVERSETRANSPOSE;\\n\\nvarying vec3 v_Normal;\\n\\nvoid main() {\\n v_Normal = normalize((normalMatrix * vec4(normal, 0.0)).xyz);\\n gl_Position = worldViewProjection * vec4(position, 1.0);\\n}\\n@end\\n\\n\\n@export ecgl.atmosphere.fragment\\nuniform mat4 viewTranspose: VIEWTRANSPOSE;\\nuniform float glowPower;\\nuniform vec3 glowColor;\\n\\nvarying vec3 v_Normal;\\n\\nvoid main() {\\n float intensity = pow(1.0 - dot(v_Normal, (viewTranspose * vec4(0.0, 0.0, 1.0, 0.0)).xyz), glowPower);\\n gl_FragColor = vec4(glowColor, intensity * intensity);\\n}\\n@end\";","import * as echarts from 'echarts/lib/echarts';\nimport graphicGL from '../../util/graphicGL';\nimport OrbitControl from '../../util/OrbitControl';\nimport SceneHelper from '../common/SceneHelper';\nimport sunCalc from '../../util/sunCalc';\nimport retrieve from '../../util/retrieve';\nimport utilShaderCode from 'claygl/src/shader/source/util.glsl.js';\nimport atmosphereShaderCode from './atmosphere.glsl.js';\ngraphicGL.Shader['import'](utilShaderCode);\ngraphicGL.Shader['import'](atmosphereShaderCode);\nexport default echarts.ComponentView.extend({\n type: 'globe',\n __ecgl__: true,\n _displacementScale: 0,\n init: function (ecModel, api) {\n this.groupGL = new graphicGL.Node();\n /**\n * @type {clay.geometry.Sphere}\n * @private\n */\n\n this._sphereGeometry = new graphicGL.SphereGeometry({\n widthSegments: 200,\n heightSegments: 100,\n dynamic: true\n });\n this._overlayGeometry = new graphicGL.SphereGeometry({\n widthSegments: 80,\n heightSegments: 40\n });\n /**\n * @type {clay.geometry.Plane}\n */\n\n this._planeGeometry = new graphicGL.PlaneGeometry();\n /**\n * @type {clay.geometry.Mesh}\n */\n\n this._earthMesh = new graphicGL.Mesh({\n renderNormal: true\n });\n /**\n * @type {clay.geometry.Mesh}\n */\n\n this._atmosphereMesh = new graphicGL.Mesh();\n this._atmosphereGeometry = new graphicGL.SphereGeometry({\n widthSegments: 80,\n heightSegments: 40\n });\n this._atmosphereMaterial = new graphicGL.Material({\n shader: new graphicGL.Shader(graphicGL.Shader.source('ecgl.atmosphere.vertex'), graphicGL.Shader.source('ecgl.atmosphere.fragment')),\n transparent: true\n });\n this._atmosphereMesh.geometry = this._atmosphereGeometry;\n this._atmosphereMesh.material = this._atmosphereMaterial;\n this._atmosphereMesh.frontFace = graphicGL.Mesh.CW;\n this._lightRoot = new graphicGL.Node();\n this._sceneHelper = new SceneHelper();\n\n this._sceneHelper.initLight(this._lightRoot);\n\n this.groupGL.add(this._atmosphereMesh);\n this.groupGL.add(this._earthMesh);\n this._control = new OrbitControl({\n zr: api.getZr()\n });\n\n this._control.init();\n\n this._layerMeshes = {};\n },\n render: function (globeModel, ecModel, api) {\n var coordSys = globeModel.coordinateSystem;\n var shading = globeModel.get('shading'); // Always have light.\n\n coordSys.viewGL.add(this._lightRoot);\n\n if (globeModel.get('show')) {\n // Add self to scene;\n coordSys.viewGL.add(this.groupGL);\n } else {\n coordSys.viewGL.remove(this.groupGL);\n }\n\n this._sceneHelper.setScene(coordSys.viewGL.scene); // Set post effect\n\n\n coordSys.viewGL.setPostEffect(globeModel.getModel('postEffect'), api);\n coordSys.viewGL.setTemporalSuperSampling(globeModel.getModel('temporalSuperSampling'));\n var earthMesh = this._earthMesh;\n earthMesh.geometry = this._sphereGeometry;\n var shadingPrefix = 'ecgl.' + shading;\n\n if (!earthMesh.material || earthMesh.material.shader.name !== shadingPrefix) {\n earthMesh.material = graphicGL.createMaterial(shadingPrefix);\n }\n\n graphicGL.setMaterialFromModel(shading, earthMesh.material, globeModel, api);\n ['roughnessMap', 'metalnessMap', 'detailMap', 'normalMap'].forEach(function (texName) {\n var texture = earthMesh.material.get(texName);\n\n if (texture) {\n texture.flipY = false;\n }\n });\n earthMesh.material.set('color', graphicGL.parseColor(globeModel.get('baseColor'))); // shrink a little\n\n var scale = coordSys.radius * 0.99;\n earthMesh.scale.set(scale, scale, scale);\n\n if (globeModel.get('atmosphere.show')) {\n earthMesh.material.define('both', 'ATMOSPHERE_ENABLED');\n this._atmosphereMesh.invisible = false;\n\n this._atmosphereMaterial.setUniforms({\n glowPower: globeModel.get('atmosphere.glowPower') || 6.0,\n glowColor: globeModel.get('atmosphere.color') || '#ffffff'\n });\n\n earthMesh.material.setUniforms({\n glowPower: globeModel.get('atmosphere.innerGlowPower') || 2.0,\n glowColor: globeModel.get('atmosphere.color') || '#ffffff'\n });\n var offset = globeModel.get('atmosphere.offset') || 5;\n\n this._atmosphereMesh.scale.set(scale + offset, scale + offset, scale + offset);\n } else {\n earthMesh.material.undefine('both', 'ATMOSPHERE_ENABLED');\n this._atmosphereMesh.invisible = true;\n }\n\n var diffuseTexture = earthMesh.material.setTextureImage('diffuseMap', globeModel.get('baseTexture'), api, {\n flipY: false,\n anisotropic: 8\n });\n\n if (diffuseTexture && diffuseTexture.surface) {\n diffuseTexture.surface.attachToMesh(earthMesh);\n } // Update bump map\n\n\n var bumpTexture = earthMesh.material.setTextureImage('bumpMap', globeModel.get('heightTexture'), api, {\n flipY: false,\n anisotropic: 8\n });\n\n if (bumpTexture && bumpTexture.surface) {\n bumpTexture.surface.attachToMesh(earthMesh);\n }\n\n earthMesh.material[globeModel.get('postEffect.enable') ? 'define' : 'undefine']('fragment', 'SRGB_DECODE');\n\n this._updateLight(globeModel, api);\n\n this._displaceVertices(globeModel, api);\n\n this._updateViewControl(globeModel, api);\n\n this._updateLayers(globeModel, api);\n },\n afterRender: function (globeModel, ecModel, api, layerGL) {\n // Create ambient cubemap after render because we need to know the renderer.\n // TODO\n var renderer = layerGL.renderer;\n\n this._sceneHelper.updateAmbientCubemap(renderer, globeModel, api);\n\n this._sceneHelper.updateSkybox(renderer, globeModel, api);\n },\n _updateLayers: function (globeModel, api) {\n var coordSys = globeModel.coordinateSystem;\n var layers = globeModel.get('layers');\n var lastDistance = coordSys.radius;\n var layerDiffuseTextures = [];\n var layerDiffuseIntensity = [];\n var layerEmissiveTextures = [];\n var layerEmissionIntensity = [];\n echarts.util.each(layers, function (layerOption) {\n var layerModel = new echarts.Model(layerOption);\n var layerType = layerModel.get('type');\n var texture = graphicGL.loadTexture(layerModel.get('texture'), api, {\n flipY: false,\n anisotropic: 8\n });\n\n if (texture.surface) {\n texture.surface.attachToMesh(this._earthMesh);\n }\n\n if (layerType === 'blend') {\n var blendTo = layerModel.get('blendTo');\n var intensity = retrieve.firstNotNull(layerModel.get('intensity'), 1.0);\n\n if (blendTo === 'emission') {\n layerEmissiveTextures.push(texture);\n layerEmissionIntensity.push(intensity);\n } else {\n // Default is albedo\n layerDiffuseTextures.push(texture);\n layerDiffuseIntensity.push(intensity);\n }\n } else {\n // Default use overlay\n var id = layerModel.get('id');\n var overlayMesh = this._layerMeshes[id];\n\n if (!overlayMesh) {\n overlayMesh = this._layerMeshes[id] = new graphicGL.Mesh({\n geometry: this._overlayGeometry,\n castShadow: false,\n ignorePicking: true\n });\n }\n\n var shading = layerModel.get('shading');\n\n if (shading === 'lambert') {\n overlayMesh.material = overlayMesh.__lambertMaterial || new graphicGL.Material({\n autoUpdateTextureStatus: false,\n shader: graphicGL.createShader('ecgl.lambert'),\n transparent: true,\n depthMask: false\n });\n overlayMesh.__lambertMaterial = overlayMesh.material;\n } else {\n // color\n overlayMesh.material = overlayMesh.__colorMaterial || new graphicGL.Material({\n autoUpdateTextureStatus: false,\n shader: graphicGL.createShader('ecgl.color'),\n transparent: true,\n depthMask: false\n });\n overlayMesh.__colorMaterial = overlayMesh.material;\n } // overlay should be transparent if texture is not loaded yet.\n\n\n overlayMesh.material.enableTexture('diffuseMap');\n var distance = layerModel.get('distance'); // Based on distance of last layer\n\n var radius = lastDistance + (distance == null ? coordSys.radius / 100 : distance);\n overlayMesh.scale.set(radius, radius, radius);\n lastDistance = radius; // FIXME Exists blink.\n\n var blankTexture = this._blankTexture || (this._blankTexture = graphicGL.createBlankTexture('rgba(255, 255, 255, 0)'));\n overlayMesh.material.set('diffuseMap', blankTexture);\n graphicGL.loadTexture(layerModel.get('texture'), api, {\n flipY: false,\n anisotropic: 8\n }, function (texture) {\n if (texture.surface) {\n texture.surface.attachToMesh(overlayMesh);\n }\n\n overlayMesh.material.set('diffuseMap', texture);\n api.getZr().refresh();\n });\n layerModel.get('show') ? this.groupGL.add(overlayMesh) : this.groupGL.remove(overlayMesh);\n }\n }, this);\n var earthMaterial = this._earthMesh.material;\n earthMaterial.define('fragment', 'LAYER_DIFFUSEMAP_COUNT', layerDiffuseTextures.length);\n earthMaterial.define('fragment', 'LAYER_EMISSIVEMAP_COUNT', layerEmissiveTextures.length);\n earthMaterial.set('layerDiffuseMap', layerDiffuseTextures);\n earthMaterial.set('layerDiffuseIntensity', layerDiffuseIntensity);\n earthMaterial.set('layerEmissiveMap', layerEmissiveTextures);\n earthMaterial.set('layerEmissionIntensity', layerEmissionIntensity);\n var debugWireframeModel = globeModel.getModel('debug.wireframe');\n\n if (debugWireframeModel.get('show')) {\n earthMaterial.define('both', 'WIREFRAME_TRIANGLE');\n var color = graphicGL.parseColor(debugWireframeModel.get('lineStyle.color') || 'rgba(0,0,0,0.5)');\n var width = retrieve.firstNotNull(debugWireframeModel.get('lineStyle.width'), 1);\n earthMaterial.set('wireframeLineWidth', width);\n earthMaterial.set('wireframeLineColor', color);\n } else {\n earthMaterial.undefine('both', 'WIREFRAME_TRIANGLE');\n }\n },\n _updateViewControl: function (globeModel, api) {\n var coordSys = globeModel.coordinateSystem; // Update camera\n\n var viewControlModel = globeModel.getModel('viewControl');\n var camera = coordSys.viewGL.camera;\n var self = this;\n\n function makeAction() {\n return {\n type: 'globeChangeCamera',\n alpha: control.getAlpha(),\n beta: control.getBeta(),\n distance: control.getDistance() - coordSys.radius,\n center: control.getCenter(),\n from: self.uid,\n globeId: globeModel.id\n };\n } // Update control\n\n\n var control = this._control;\n control.setViewGL(coordSys.viewGL);\n var coord = viewControlModel.get('targetCoord');\n var alpha, beta;\n\n if (coord != null) {\n beta = coord[0] + 90;\n alpha = coord[1];\n }\n\n control.setFromViewControlModel(viewControlModel, {\n baseDistance: coordSys.radius,\n alpha: alpha,\n beta: beta\n });\n control.off('update');\n control.on('update', function () {\n api.dispatchAction(makeAction());\n });\n },\n _displaceVertices: function (globeModel, api) {\n var displacementQuality = globeModel.get('displacementQuality');\n var showDebugWireframe = globeModel.get('debug.wireframe.show');\n var globe = globeModel.coordinateSystem;\n\n if (!globeModel.isDisplacementChanged() && displacementQuality === this._displacementQuality && showDebugWireframe === this._showDebugWireframe) {\n return;\n }\n\n this._displacementQuality = displacementQuality;\n this._showDebugWireframe = showDebugWireframe;\n var geometry = this._sphereGeometry;\n var widthSegments = {\n low: 100,\n medium: 200,\n high: 400,\n ultra: 800\n }[displacementQuality] || 200;\n var heightSegments = widthSegments / 2;\n\n if (geometry.widthSegments !== widthSegments || showDebugWireframe) {\n geometry.widthSegments = widthSegments;\n geometry.heightSegments = heightSegments;\n geometry.build();\n }\n\n this._doDisplaceVertices(geometry, globe);\n\n if (showDebugWireframe) {\n geometry.generateBarycentric();\n }\n },\n _doDisplaceVertices: function (geometry, globe) {\n var positionArr = geometry.attributes.position.value;\n var uvArr = geometry.attributes.texcoord0.value;\n var originalPositionArr = geometry.__originalPosition;\n\n if (!originalPositionArr || originalPositionArr.length !== positionArr.length) {\n originalPositionArr = new Float32Array(positionArr.length);\n originalPositionArr.set(positionArr);\n geometry.__originalPosition = originalPositionArr;\n }\n\n var width = globe.displacementWidth;\n var height = globe.displacementHeight;\n var data = globe.displacementData;\n\n for (var i = 0; i < geometry.vertexCount; i++) {\n var i3 = i * 3;\n var i2 = i * 2;\n var x = originalPositionArr[i3 + 1];\n var y = originalPositionArr[i3 + 2];\n var z = originalPositionArr[i3 + 3];\n var u = uvArr[i2++];\n var v = uvArr[i2++];\n var j = Math.round(u * (width - 1));\n var k = Math.round(v * (height - 1));\n var idx = k * width + j;\n var scale = data ? data[idx] : 0;\n positionArr[i3 + 1] = x + x * scale;\n positionArr[i3 + 2] = y + y * scale;\n positionArr[i3 + 3] = z + z * scale;\n }\n\n geometry.generateVertexNormals();\n geometry.dirty();\n geometry.updateBoundingBox();\n },\n _updateLight: function (globeModel, api) {\n var earthMesh = this._earthMesh;\n\n this._sceneHelper.updateLight(globeModel);\n\n var mainLight = this._sceneHelper.mainLight; // Put sun in the right position\n\n var time = globeModel.get('light.main.time') || new Date(); // http://en.wikipedia.org/wiki/Azimuth\n\n var pos = sunCalc.getPosition(echarts.number.parseDate(time), 0, 0);\n var r0 = Math.cos(pos.altitude); // FIXME How to calculate the y ?\n\n mainLight.position.y = -r0 * Math.cos(pos.azimuth);\n mainLight.position.x = Math.sin(pos.altitude);\n mainLight.position.z = r0 * Math.sin(pos.azimuth);\n mainLight.lookAt(earthMesh.getWorldPosition());\n },\n dispose: function (ecModel, api) {\n this.groupGL.removeAll();\n\n this._control.dispose();\n }\n});","import glmatrix from 'claygl/src/dep/glmatrix';\nvar vec3 = glmatrix.vec3;\n\nfunction Globe(radius) {\n this.radius = radius;\n this.viewGL = null;\n this.altitudeAxis; // Displacement data provided by texture.\n\n this.displacementData = null;\n this.displacementWidth;\n this.displacementHeight;\n}\n\nGlobe.prototype = {\n constructor: Globe,\n dimensions: ['lng', 'lat', 'alt'],\n type: 'globe',\n containPoint: function () {},\n setDisplacementData: function (data, width, height) {\n this.displacementData = data;\n this.displacementWidth = width;\n this.displacementHeight = height;\n },\n _getDisplacementScale: function (lng, lat) {\n var i = (lng + 180) / 360 * (this.displacementWidth - 1);\n var j = (90 - lat) / 180 * (this.displacementHeight - 1); // NEAREST SAMPLING\n // TODO Better bilinear sampling\n\n var idx = Math.round(i) + Math.round(j) * this.displacementWidth;\n return this.displacementData[idx];\n },\n dataToPoint: function (data, out) {\n var lng = data[0];\n var lat = data[1]; // Default have 0 altitude\n\n var altVal = data[2] || 0;\n var r = this.radius;\n\n if (this.displacementData) {\n r *= 1 + this._getDisplacementScale(lng, lat);\n }\n\n if (this.altitudeAxis) {\n r += this.altitudeAxis.dataToCoord(altVal);\n }\n\n lng = lng * Math.PI / 180;\n lat = lat * Math.PI / 180;\n var r0 = Math.cos(lat) * r;\n out = out || []; // PENDING\n\n out[0] = -r0 * Math.cos(lng + Math.PI);\n out[1] = Math.sin(lat) * r;\n out[2] = r0 * Math.sin(lng + Math.PI);\n return out;\n },\n pointToData: function (point, out) {\n var x = point[0];\n var y = point[1];\n var z = point[2];\n var len = vec3.len(point);\n x /= len;\n y /= len;\n z /= len;\n var theta = Math.asin(y);\n var phi = Math.atan2(z, -x);\n\n if (phi < 0) {\n phi = Math.PI * 2 + phi;\n }\n\n var lat = theta * 180 / Math.PI;\n var lng = phi * 180 / Math.PI - 180;\n out = out || [];\n out[0] = lng;\n out[1] = lat;\n out[2] = len - this.radius;\n\n if (this.altitudeAxis) {\n out[2] = this.altitudeAxis.coordToData(out[2]);\n }\n\n return out;\n }\n};\nexport default Globe;","import Globe from './globe/Globe';\nimport * as echarts from 'echarts/lib/echarts';\nimport { getLayoutRect } from 'echarts/lib/util/layout';\nimport ViewGL from '../core/ViewGL';\nimport retrieve from '../util/retrieve';\nimport graphicGL from '../util/graphicGL';\n\nfunction getDisplacementData(img, displacementScale) {\n var canvas = document.createElement('canvas');\n var ctx = canvas.getContext('2d');\n var width = img.width;\n var height = img.height;\n canvas.width = width;\n canvas.height = height;\n ctx.drawImage(img, 0, 0, width, height);\n var rgbaArr = ctx.getImageData(0, 0, width, height).data;\n var displacementArr = new Float32Array(rgbaArr.length / 4);\n\n for (var i = 0; i < rgbaArr.length / 4; i++) {\n var x = rgbaArr[i * 4];\n displacementArr[i] = x / 255 * displacementScale;\n }\n\n return {\n data: displacementArr,\n width: width,\n height: height\n };\n}\n\nfunction resizeGlobe(globeModel, api) {\n // Use left/top/width/height\n var boxLayoutOption = globeModel.getBoxLayoutParams();\n var viewport = getLayoutRect(boxLayoutOption, {\n width: api.getWidth(),\n height: api.getHeight()\n }); // Flip Y\n\n viewport.y = api.getHeight() - viewport.y - viewport.height;\n this.viewGL.setViewport(viewport.x, viewport.y, viewport.width, viewport.height, api.getDevicePixelRatio());\n this.radius = globeModel.get('globeRadius');\n var outerRadius = globeModel.get('globeOuterRadius');\n\n if (this.altitudeAxis) {\n this.altitudeAxis.setExtent(0, outerRadius - this.radius);\n }\n}\n\nfunction updateGlobe(ecModel, api) {\n var altitudeDataExtent = [Infinity, -Infinity];\n ecModel.eachSeries(function (seriesModel) {\n if (seriesModel.coordinateSystem !== this) {\n return;\n } // Get altitude data extent.\n\n\n var data = seriesModel.getData();\n var altDims = seriesModel.coordDimToDataDim('alt');\n var altDim = altDims && altDims[0];\n\n if (altDim) {\n // TODO altitiude is in coords of lines.\n var dataExtent = data.getDataExtent(altDim, true);\n altitudeDataExtent[0] = Math.min(altitudeDataExtent[0], dataExtent[0]);\n altitudeDataExtent[1] = Math.max(altitudeDataExtent[1], dataExtent[1]);\n }\n }, this); // Create altitude axis\n\n if (altitudeDataExtent && isFinite(altitudeDataExtent[1] - altitudeDataExtent[0])) {\n var scale = echarts.helper.createScale(altitudeDataExtent, {\n type: 'value',\n // PENDING\n min: 'dataMin',\n max: 'dataMax'\n });\n this.altitudeAxis = new echarts.Axis('altitude', scale); // Resize again\n\n this.resize(this.model, api);\n }\n}\n\nvar globeCreator = {\n dimensions: Globe.prototype.dimensions,\n create: function (ecModel, api) {\n var globeList = [];\n ecModel.eachComponent('globe', function (globeModel) {\n // FIXME\n globeModel.__viewGL = globeModel.__viewGL || new ViewGL();\n var globe = new Globe();\n globe.viewGL = globeModel.__viewGL;\n globeModel.coordinateSystem = globe;\n globe.model = globeModel;\n globeList.push(globe); // Inject resize\n\n globe.resize = resizeGlobe;\n globe.resize(globeModel, api);\n globe.update = updateGlobe;\n });\n ecModel.eachSeries(function (seriesModel) {\n if (seriesModel.get('coordinateSystem') === 'globe') {\n var globeModel = seriesModel.getReferringComponents('globe').models[0];\n\n if (!globeModel) {\n globeModel = ecModel.getComponent('globe');\n }\n\n if (!globeModel) {\n throw new Error('globe \"' + retrieve.firstNotNull(seriesModel.get('globe3DIndex'), seriesModel.get('globe3DId'), 0) + '\" not found');\n }\n\n var coordSys = globeModel.coordinateSystem;\n seriesModel.coordinateSystem = coordSys;\n }\n });\n ecModel.eachComponent('globe', function (globeModel, idx) {\n var globe = globeModel.coordinateSystem; // Update displacement data\n\n var displacementTextureValue = globeModel.getDisplacementTexture();\n var displacementScale = globeModel.getDisplacemenScale();\n\n if (globeModel.isDisplacementChanged()) {\n if (globeModel.hasDisplacement()) {\n var immediateLoaded = true;\n graphicGL.loadTexture(displacementTextureValue, api, function (texture) {\n var img = texture.image;\n var displacementData = getDisplacementData(img, displacementScale);\n globeModel.setDisplacementData(displacementData.data, displacementData.width, displacementData.height);\n\n if (!immediateLoaded) {\n // Update layouts\n api.dispatchAction({\n type: 'globeUpdateDisplacment'\n });\n }\n });\n immediateLoaded = false;\n } else {\n globe.setDisplacementData(null, 0, 0);\n }\n\n globe.setDisplacementData(globeModel.displacementData, globeModel.displacementWidth, globeModel.displacementHeight);\n }\n });\n return globeList;\n }\n};\nexport default globeCreator;","// TODO ECharts GL must be imported whatever component,charts is imported.\nimport '../../echarts-gl';\nimport GlobeModel from './GlobeModel';\nimport GlobeView from './GlobeView';\nimport globeCreator from '../../coord/globeCreator';\nexport function install(registers) {\n registers.registerComponentModel(GlobeModel);\n registers.registerComponentView(GlobeView);\n registers.registerCoordinateSystem('globe', globeCreator);\n registers.registerAction({\n type: 'globeChangeCamera',\n event: 'globecamerachanged',\n update: 'series:updateCamera'\n }, function (payload, ecModel) {\n ecModel.eachComponent({\n mainType: 'globe',\n query: payload\n }, function (componentModel) {\n componentModel.setView(payload);\n });\n });\n registers.registerAction({\n type: 'globeUpdateDisplacment',\n event: 'globedisplacementupdated',\n update: 'update'\n }, function (payload, ecModel) {// Noop\n });\n}","import { use } from 'echarts/lib/echarts';\nimport { install } from './globe/install';\nuse(install);","import * as echarts from 'echarts/lib/echarts';\nimport componentPostEffectMixin from '../common/componentPostEffectMixin';\nimport componentLightMixin from '../common/componentLightMixin';\nvar MAPBOX_CAMERA_OPTION = ['zoom', 'center', 'pitch', 'bearing'];\nvar Mapbox3DModel = echarts.ComponentModel.extend({\n type: 'mapbox3D',\n layoutMode: 'box',\n coordinateSystem: null,\n defaultOption: {\n zlevel: -10,\n style: 'mapbox://styles/mapbox/light-v9',\n center: [0, 0],\n zoom: 0,\n pitch: 0,\n bearing: 0,\n light: {\n main: {\n alpha: 20,\n beta: 30\n }\n },\n altitudeScale: 1,\n // Default depend on altitudeScale\n boxHeight: 'auto'\n },\n getMapboxCameraOption: function () {\n var self = this;\n return MAPBOX_CAMERA_OPTION.reduce(function (obj, key) {\n obj[key] = self.get(key);\n return obj;\n }, {});\n },\n setMapboxCameraOption: function (option) {\n if (option != null) {\n MAPBOX_CAMERA_OPTION.forEach(function (key) {\n if (option[key] != null) {\n this.option[key] = option[key];\n }\n }, this);\n }\n },\n\n /**\n * Get mapbox instance\n */\n getMapbox: function () {\n return this._mapbox;\n },\n setMapbox: function (mapbox) {\n this._mapbox = mapbox;\n }\n});\necharts.util.merge(Mapbox3DModel.prototype, componentPostEffectMixin);\necharts.util.merge(Mapbox3DModel.prototype, componentLightMixin);\nexport default Mapbox3DModel;","/**\n * @constructor\n * @alias module:echarts-gl/component/mapbox3D/Mapbox3DLayer\n * @param {string} id Layer ID\n * @param {module:zrender/ZRender} zr\n */\nfunction Mapbox3DLayer(id, zr) {\n this.id = id;\n this.zr = zr;\n this.dom = document.createElement('div');\n this.dom.style.cssText = 'position:absolute;left:0;right:0;top:0;bottom:0;'; // FIXME If in module environment.\n\n if (!mapboxgl) {\n throw new Error('Mapbox GL library must be included. See https://www.mapbox.com/mapbox-gl-js/api/');\n }\n\n this._mapbox = new mapboxgl.Map({\n container: this.dom\n }); // Proxy events\n\n this._initEvents();\n}\n\nMapbox3DLayer.prototype.setUnpainted = function () {};\n\nMapbox3DLayer.prototype.resize = function () {\n this._mapbox.resize();\n};\n\nMapbox3DLayer.prototype.getMapbox = function () {\n return this._mapbox;\n};\n\nMapbox3DLayer.prototype.clear = function () {};\n\nMapbox3DLayer.prototype.refresh = function () {\n this._mapbox.resize();\n};\n\nvar EVENTS = ['mousedown', 'mouseup', 'click', 'dblclick', 'mousemove', 'mousewheel', 'wheel', 'touchstart', 'touchend', 'touchmove', 'touchcancel'];\n\nMapbox3DLayer.prototype._initEvents = function () {\n // Event is bound on canvas container.\n var mapboxRoot = this._mapbox.getCanvasContainer();\n\n this._handlers = this._handlers || {\n contextmenu: function (e) {\n e.preventDefault();\n return false;\n }\n };\n EVENTS.forEach(function (eName) {\n this._handlers[eName] = function (e) {\n var obj = {};\n\n for (var name in e) {\n obj[name] = e[name];\n }\n\n obj.bubbles = false;\n var newE = new e.constructor(e.type, obj);\n mapboxRoot.dispatchEvent(newE);\n };\n\n this.zr.dom.addEventListener(eName, this._handlers[eName]);\n }, this); // PENDING\n\n this.zr.dom.addEventListener('contextmenu', this._handlers.contextmenu);\n};\n\nMapbox3DLayer.prototype.dispose = function () {\n EVENTS.forEach(function (eName) {\n this.zr.dom.removeEventListener(eName, this._handlers[eName]);\n }, this);\n};\n\nexport default Mapbox3DLayer;","export default \"\\n@export ecgl.displayShadow.vertex\\n\\n@import ecgl.common.transformUniforms\\n\\n@import ecgl.common.uv.header\\n\\n@import ecgl.common.attributes\\n\\nvarying vec3 v_WorldPosition;\\n\\nvarying vec3 v_Normal;\\n\\nvoid main()\\n{\\n @import ecgl.common.uv.main\\n v_Normal = normalize((worldInverseTranspose * vec4(normal, 0.0)).xyz);\\n\\n v_WorldPosition = (world * vec4(position, 1.0)).xyz;\\n gl_Position = worldViewProjection * vec4(position, 1.0);\\n}\\n\\n@end\\n\\n\\n@export ecgl.displayShadow.fragment\\n\\n@import ecgl.common.uv.fragmentHeader\\n\\nvarying vec3 v_Normal;\\nvarying vec3 v_WorldPosition;\\n\\nuniform float roughness: 0.2;\\n\\n#ifdef DIRECTIONAL_LIGHT_COUNT\\n@import clay.header.directional_light\\n#endif\\n\\n@import ecgl.common.ssaoMap.header\\n\\n@import clay.plugin.compute_shadow_map\\n\\nvoid main()\\n{\\n float shadow = 1.0;\\n\\n @import ecgl.common.ssaoMap.main\\n\\n#if defined(DIRECTIONAL_LIGHT_COUNT) && defined(DIRECTIONAL_LIGHT_SHADOWMAP_COUNT)\\n float shadowContribsDir[DIRECTIONAL_LIGHT_COUNT];\\n if(shadowEnabled)\\n {\\n computeShadowOfDirectionalLights(v_WorldPosition, shadowContribsDir);\\n }\\n for (int i = 0; i < DIRECTIONAL_LIGHT_COUNT; i++) {\\n shadow = min(shadow, shadowContribsDir[i] * 0.5 + 0.5);\\n }\\n#endif\\n\\n shadow *= 0.5 + ao * 0.5;\\n shadow = clamp(shadow, 0.0, 1.0);\\n\\n gl_FragColor = vec4(vec3(0.0), 1.0 - shadow);\\n}\\n\\n@end\";","import * as echarts from 'echarts/lib/echarts';\nimport Mapbox3DLayer from './Mapbox3DLayer';\nimport SceneHelper from '../common/SceneHelper';\nimport graphicGL from '../../util/graphicGL';\nimport displayShadowGLSL from '../../util/shader/displayShadow.glsl.js';\ngraphicGL.Shader.import(displayShadowGLSL);\nvar TILE_SIZE = 512;\nexport default echarts.ComponentView.extend({\n type: 'mapbox3D',\n __ecgl__: true,\n init: function (ecModel, api) {\n var zr = api.getZr();\n this._zrLayer = new Mapbox3DLayer('mapbox3D', zr);\n zr.painter.insertLayer(-1000, this._zrLayer);\n this._lightRoot = new graphicGL.Node();\n this._sceneHelper = new SceneHelper(this._lightRoot);\n\n this._sceneHelper.initLight(this._lightRoot);\n\n var mapbox = this._zrLayer.getMapbox();\n\n var dispatchInteractAction = this._dispatchInteractAction.bind(this, api, mapbox); // PENDING\n\n\n ['zoom', 'rotate', 'drag', 'pitch', 'rotate', 'move'].forEach(function (eName) {\n mapbox.on(eName, dispatchInteractAction);\n });\n this._groundMesh = new graphicGL.Mesh({\n geometry: new graphicGL.PlaneGeometry(),\n material: new graphicGL.Material({\n shader: new graphicGL.Shader({\n vertex: graphicGL.Shader.source('ecgl.displayShadow.vertex'),\n fragment: graphicGL.Shader.source('ecgl.displayShadow.fragment')\n }),\n depthMask: false\n }),\n // Render first\n renderOrder: -100,\n culling: false,\n castShadow: false,\n $ignorePicking: true,\n renderNormal: true\n });\n },\n render: function (mapbox3DModel, ecModel, api) {\n var mapbox = this._zrLayer.getMapbox();\n\n var styleDesc = mapbox3DModel.get('style');\n var styleStr = JSON.stringify(styleDesc);\n\n if (styleStr !== this._oldStyleStr) {\n if (styleDesc) {\n mapbox.setStyle(styleDesc);\n }\n }\n\n this._oldStyleStr = styleStr;\n mapbox.setCenter(mapbox3DModel.get('center'));\n mapbox.setZoom(mapbox3DModel.get('zoom'));\n mapbox.setPitch(mapbox3DModel.get('pitch'));\n mapbox.setBearing(mapbox3DModel.get('bearing'));\n mapbox3DModel.setMapbox(mapbox);\n var coordSys = mapbox3DModel.coordinateSystem; // Not add to rootNode. Or light direction will be stretched by rootNode scale\n\n coordSys.viewGL.scene.add(this._lightRoot);\n coordSys.viewGL.add(this._groundMesh);\n\n this._updateGroundMesh(); // Update lights\n\n\n this._sceneHelper.setScene(coordSys.viewGL.scene);\n\n this._sceneHelper.updateLight(mapbox3DModel); // Update post effects\n\n\n coordSys.viewGL.setPostEffect(mapbox3DModel.getModel('postEffect'), api);\n coordSys.viewGL.setTemporalSuperSampling(mapbox3DModel.getModel('temporalSuperSampling'));\n this._mapbox3DModel = mapbox3DModel;\n },\n afterRender: function (mapbox3DModel, ecModel, api, layerGL) {\n var renderer = layerGL.renderer;\n\n this._sceneHelper.updateAmbientCubemap(renderer, mapbox3DModel, api);\n\n this._sceneHelper.updateSkybox(renderer, mapbox3DModel, api); // FIXME If other series changes coordinate system.\n // FIXME When doing progressive rendering.\n\n\n mapbox3DModel.coordinateSystem.viewGL.scene.traverse(function (mesh) {\n if (mesh.material) {\n mesh.material.define('fragment', 'NORMAL_UP_AXIS', 2);\n mesh.material.define('fragment', 'NORMAL_FRONT_AXIS', 1);\n }\n });\n },\n updateCamera: function (mapbox3DModel, ecModel, api, payload) {\n mapbox3DModel.coordinateSystem.setCameraOption(payload);\n\n this._updateGroundMesh();\n\n api.getZr().refresh();\n },\n _dispatchInteractAction: function (api, mapbox, mapbox3DModel) {\n api.dispatchAction({\n type: 'mapbox3DChangeCamera',\n pitch: mapbox.getPitch(),\n zoom: mapbox.getZoom(),\n center: mapbox.getCenter().toArray(),\n bearing: mapbox.getBearing(),\n mapbox3DId: this._mapbox3DModel && this._mapbox3DModel.id\n });\n },\n _updateGroundMesh: function () {\n if (this._mapbox3DModel) {\n var coordSys = this._mapbox3DModel.coordinateSystem;\n var pt = coordSys.dataToPoint(coordSys.center);\n\n this._groundMesh.position.set(pt[0], pt[1], -0.001);\n\n var plane = new graphicGL.Plane(new graphicGL.Vector3(0, 0, 1), 0);\n var ray1 = coordSys.viewGL.camera.castRay(new graphicGL.Vector2(-1, -1));\n var ray2 = coordSys.viewGL.camera.castRay(new graphicGL.Vector2(1, 1));\n var pos0 = ray1.intersectPlane(plane);\n var pos1 = ray2.intersectPlane(plane);\n var scale = pos0.dist(pos1) / coordSys.viewGL.rootNode.scale.x;\n\n this._groundMesh.scale.set(scale, scale, 1);\n }\n },\n dispose: function (ecModel, api) {\n if (this._zrLayer) {\n this._zrLayer.dispose();\n }\n\n api.getZr().painter.delLayer(-1000);\n }\n});","import glmatrix from 'claygl/src/dep/glmatrix';\nvar mat4 = glmatrix.mat4;\nvar TILE_SIZE = 512;\nvar FOV = 0.6435011087932844;\nvar PI = Math.PI;\nvar WORLD_SCALE = 1 / 10;\n\nfunction MapServiceCoordSys3D() {\n /**\n * Width of mapbox viewport\n */\n this.width = 0;\n /**\n * Height of mapbox viewport\n */\n\n this.height = 0;\n this.altitudeScale = 1; // TODO Change boxHeight won't have animation.\n\n this.boxHeight = 'auto'; // Set by mapbox creator\n\n this.altitudeExtent;\n this.bearing = 0;\n this.pitch = 0;\n this.center = [0, 0];\n this._origin;\n this.zoom = 0;\n this._initialZoom; // Some parameters for different map services.\n\n this.maxPitch = 60;\n this.zoomOffset = 0;\n}\n\nMapServiceCoordSys3D.prototype = {\n constructor: MapServiceCoordSys3D,\n dimensions: ['lng', 'lat', 'alt'],\n containPoint: function () {},\n setCameraOption: function (option) {\n this.bearing = option.bearing;\n this.pitch = option.pitch;\n this.center = option.center;\n this.zoom = option.zoom;\n\n if (!this._origin) {\n this._origin = this.projectOnTileWithScale(this.center, TILE_SIZE);\n }\n\n if (this._initialZoom == null) {\n this._initialZoom = this.zoom;\n }\n\n this.updateTransform();\n },\n // https://github.com/mapbox/mapbox-gl-js/blob/master/src/geo/transform.js#L479\n updateTransform: function () {\n if (!this.height) {\n return;\n }\n\n var cameraToCenterDistance = 0.5 / Math.tan(FOV / 2) * this.height * WORLD_SCALE; // Convert to radian.\n\n var pitch = Math.max(Math.min(this.pitch, this.maxPitch), 0) / 180 * Math.PI; // Find the distance from the center point [width/2, height/2] to the\n // center top point [width/2, 0] in Z units, using the law of sines.\n // 1 Z unit is equivalent to 1 horizontal px at the center of the map\n // (the distance between[width/2, height/2] and [width/2 + 1, height/2])\n\n var halfFov = FOV / 2;\n var groundAngle = Math.PI / 2 + pitch;\n var topHalfSurfaceDistance = Math.sin(halfFov) * cameraToCenterDistance / Math.sin(Math.PI - groundAngle - halfFov); // Calculate z distance of the farthest fragment that should be rendered.\n\n var furthestDistance = Math.cos(Math.PI / 2 - pitch) * topHalfSurfaceDistance + cameraToCenterDistance; // Add a bit extra to avoid precision problems when a fragment's distance is exactly `furthestDistance`\n\n var farZ = furthestDistance * 1.1; // Forced to be 1000\n\n if (this.pitch > 50) {\n farZ = 1000;\n } // matrix for conversion from location to GL coordinates (-1 .. 1)\n\n\n var m = [];\n mat4.perspective(m, FOV, this.width / this.height, 1, farZ);\n this.viewGL.camera.projectionMatrix.setArray(m);\n this.viewGL.camera.decomposeProjectionMatrix();\n var m = mat4.identity([]);\n var pt = this.dataToPoint(this.center); // Inverse\n\n mat4.scale(m, m, [1, -1, 1]); // Translate to altitude\n\n mat4.translate(m, m, [0, 0, -cameraToCenterDistance]);\n mat4.rotateX(m, m, pitch);\n mat4.rotateZ(m, m, -this.bearing / 180 * Math.PI); // Translate to center.\n\n mat4.translate(m, m, [-pt[0] * this.getScale() * WORLD_SCALE, -pt[1] * this.getScale() * WORLD_SCALE, 0]);\n this.viewGL.camera.viewMatrix.array = m;\n var invertM = [];\n mat4.invert(invertM, m);\n this.viewGL.camera.worldTransform.array = invertM;\n this.viewGL.camera.decomposeWorldTransform(); // scale vertically to meters per pixel (inverse of ground resolution):\n // worldSize / (circumferenceOfEarth * cos(lat * π / 180))\n\n var worldSize = TILE_SIZE * this.getScale();\n var verticalScale;\n\n if (this.altitudeExtent && !isNaN(this.boxHeight)) {\n var range = this.altitudeExtent[1] - this.altitudeExtent[0];\n verticalScale = this.boxHeight / range * this.getScale() / Math.pow(2, this._initialZoom - this.zoomOffset);\n } else {\n verticalScale = worldSize / (2 * Math.PI * 6378000 * Math.abs(Math.cos(this.center[1] * (Math.PI / 180)))) * this.altitudeScale * WORLD_SCALE;\n } // Include scale to avoid relayout when zooming\n // FIXME Camera scale may have problem in shadow\n\n\n this.viewGL.rootNode.scale.set(this.getScale() * WORLD_SCALE, this.getScale() * WORLD_SCALE, verticalScale);\n },\n getScale: function () {\n return Math.pow(2, this.zoom - this.zoomOffset);\n },\n projectOnTile: function (data, out) {\n return this.projectOnTileWithScale(data, this.getScale() * TILE_SIZE, out);\n },\n projectOnTileWithScale: function (data, scale, out) {\n var lng = data[0];\n var lat = data[1];\n var lambda2 = lng * PI / 180;\n var phi2 = lat * PI / 180;\n var x = scale * (lambda2 + PI) / (2 * PI);\n var y = scale * (PI - Math.log(Math.tan(PI / 4 + phi2 * 0.5))) / (2 * PI);\n out = out || [];\n out[0] = x;\n out[1] = y;\n return out;\n },\n unprojectFromTile: function (point, out) {\n return this.unprojectOnTileWithScale(point, this.getScale() * TILE_SIZE, out);\n },\n unprojectOnTileWithScale: function (point, scale, out) {\n var x = point[0];\n var y = point[1];\n var lambda2 = x / scale * (2 * PI) - PI;\n var phi2 = 2 * (Math.atan(Math.exp(PI - y / scale * (2 * PI))) - PI / 4);\n out = out || [];\n out[0] = lambda2 * 180 / PI;\n out[1] = phi2 * 180 / PI;\n return out;\n },\n dataToPoint: function (data, out) {\n out = this.projectOnTileWithScale(data, TILE_SIZE, out); // Add a origin to avoid precision issue in WebGL.\n\n out[0] -= this._origin[0];\n out[1] -= this._origin[1]; // PENDING\n\n out[2] = !isNaN(data[2]) ? data[2] : 0;\n\n if (!isNaN(data[2])) {\n out[2] = data[2];\n\n if (this.altitudeExtent) {\n out[2] -= this.altitudeExtent[0];\n }\n }\n\n return out;\n }\n};\nexport default MapServiceCoordSys3D;","import MapService3D from '../mapServiceCommon/MapService3D';\n\nfunction Mapbox3D() {\n MapService3D.apply(this, arguments);\n}\n\nMapbox3D.prototype = new MapService3D();\nMapbox3D.prototype.constructor = Mapbox3D;\nMapbox3D.prototype.type = 'mapbox3D';\nexport default Mapbox3D;","import retrieve from '../../util/retrieve';\nimport graphicGL from '../../util/graphicGL';\nimport ViewGL from '../../core/ViewGL';\nexport default function (serviceComponentType, ServiceCtor, afterCreate) {\n function resizeMapService3D(mapService3DModel, api) {\n var width = api.getWidth();\n var height = api.getHeight();\n var dpr = api.getDevicePixelRatio();\n this.viewGL.setViewport(0, 0, width, height, dpr);\n this.width = width;\n this.height = height;\n this.altitudeScale = mapService3DModel.get('altitudeScale');\n this.boxHeight = mapService3DModel.get('boxHeight'); // this.updateTransform();\n }\n\n function updateService3D(ecModel, api) {\n if (this.model.get('boxHeight') === 'auto') {\n return;\n }\n\n var altitudeDataExtent = [Infinity, -Infinity];\n ecModel.eachSeries(function (seriesModel) {\n if (seriesModel.coordinateSystem !== this) {\n return;\n } // Get altitude data extent.\n\n\n var data = seriesModel.getData();\n var altDim = seriesModel.coordDimToDataDim('alt')[0];\n\n if (altDim) {\n // TODO altitiude is in coords of lines.\n var dataExtent = data.getDataExtent(altDim, true);\n altitudeDataExtent[0] = Math.min(altitudeDataExtent[0], dataExtent[0]);\n altitudeDataExtent[1] = Math.max(altitudeDataExtent[1], dataExtent[1]);\n }\n }, this);\n\n if (altitudeDataExtent && isFinite(altitudeDataExtent[1] - altitudeDataExtent[0])) {\n this.altitudeExtent = altitudeDataExtent;\n }\n }\n\n return {\n dimensions: ServiceCtor.prototype.dimensions,\n create: function (ecModel, api) {\n var mapService3DList = [];\n ecModel.eachComponent(serviceComponentType, function (mapService3DModel) {\n var viewGL = mapService3DModel.__viewGL;\n\n if (!viewGL) {\n viewGL = mapService3DModel.__viewGL = new ViewGL();\n viewGL.setRootNode(new graphicGL.Node());\n }\n\n var mapService3DCoordSys = new ServiceCtor();\n mapService3DCoordSys.viewGL = mapService3DModel.__viewGL; // Inject resize\n\n mapService3DCoordSys.resize = resizeMapService3D;\n mapService3DCoordSys.resize(mapService3DModel, api);\n mapService3DList.push(mapService3DCoordSys);\n mapService3DModel.coordinateSystem = mapService3DCoordSys;\n mapService3DCoordSys.model = mapService3DModel;\n mapService3DCoordSys.update = updateService3D;\n });\n ecModel.eachSeries(function (seriesModel) {\n if (seriesModel.get('coordinateSystem') === serviceComponentType) {\n var mapService3DModel = seriesModel.getReferringComponents(serviceComponentType).models[0];\n\n if (!mapService3DModel) {\n mapService3DModel = ecModel.getComponent(serviceComponentType);\n }\n\n if (!mapService3DModel) {\n throw new Error(serviceComponentType + ' \"' + retrieve.firstNotNull(seriesModel.get(serviceComponentType + 'Index'), seriesModel.get(serviceComponentType + 'Id'), 0) + '\" not found');\n }\n\n seriesModel.coordinateSystem = mapService3DModel.coordinateSystem;\n }\n });\n afterCreate && afterCreate(mapService3DList, ecModel, api);\n return mapService3DList;\n }\n };\n}","import Mapbox3D from './mapbox3D/Mapbox3D';\nimport createMapService3DCreator from './mapServiceCommon/createMapService3DCreator';\nvar mapbox3DCreator = createMapService3DCreator('mapbox3D', Mapbox3D, function (mapbox3DList) {\n mapbox3DList.forEach(function (mapbox3D) {\n mapbox3D.setCameraOption(mapbox3D.model.getMapboxCameraOption());\n });\n});\nexport default mapbox3DCreator;","// TODO ECharts GL must be imported whatever component,charts is imported.\nimport '../../echarts-gl';\nimport Mapbox3DModel from './Mapbox3DModel';\nimport Mapbox3DView from './Mapbox3DView';\nimport mapbox3DCreator from '../../coord/mapbox3DCreator';\nexport function install(registers) {\n registers.registerComponentModel(Mapbox3DModel);\n registers.registerComponentView(Mapbox3DView);\n registers.registerCoordinateSystem('mapbox3D', mapbox3DCreator);\n registers.registerAction({\n type: 'mapbox3DChangeCamera',\n event: 'mapbox3dcamerachanged',\n update: 'mapbox3D:updateCamera'\n }, function (payload, ecModel) {\n ecModel.eachComponent({\n mainType: 'mapbox3D',\n query: payload\n }, function (componentModel) {\n componentModel.setMapboxCameraOption(payload);\n });\n });\n}","import { use } from 'echarts/lib/echarts';\nimport { install } from './mapbox3D/install';\nuse(install);","import * as echarts from 'echarts/lib/echarts';\nimport componentPostEffectMixin from '../common/componentPostEffectMixin';\nimport componentLightMixin from '../common/componentLightMixin';\nvar MAPTALKS_CAMERA_OPTION = ['zoom', 'center', 'pitch', 'bearing'];\nvar Maptalks3DModel = echarts.ComponentModel.extend({\n type: 'maptalks3D',\n layoutMode: 'box',\n coordinateSystem: null,\n defaultOption: {\n zlevel: -10,\n urlTemplate: 'http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png',\n attribution: '© OpenStreetMap contributors, © CARTO',\n center: [0, 0],\n zoom: 0,\n pitch: 0,\n bearing: 0,\n light: {\n main: {\n alpha: 20,\n beta: 30\n }\n },\n altitudeScale: 1,\n // Default depend on altitudeScale\n boxHeight: 'auto'\n },\n getMaptalksCameraOption: function () {\n var self = this;\n return MAPTALKS_CAMERA_OPTION.reduce(function (obj, key) {\n obj[key] = self.get(key);\n return obj;\n }, {});\n },\n setMaptalksCameraOption: function (option) {\n if (option != null) {\n MAPTALKS_CAMERA_OPTION.forEach(function (key) {\n if (option[key] != null) {\n this.option[key] = option[key];\n }\n }, this);\n }\n },\n\n /**\n * Get maptalks instance\n */\n getMaptalks: function () {\n return this._maptalks;\n },\n setMaptalks: function (maptalks) {\n this._maptalks = maptalks;\n }\n});\necharts.util.merge(Maptalks3DModel.prototype, componentPostEffectMixin);\necharts.util.merge(Maptalks3DModel.prototype, componentLightMixin);\nexport default Maptalks3DModel;","/**\n * @constructor\n * @alias module:echarts-gl/component/maptalks/Maptalks3DLayer\n * @param {string} id Layer ID\n * @param {module:zrender/ZRender} zr\n */\nfunction Maptalks3DLayer(id, zr, defaultCenter, defaultZoom) {\n this.id = id;\n this.zr = zr;\n this.dom = document.createElement('div');\n this.dom.style.cssText = 'position:absolute;left:0;right:0;top:0;bottom:0;'; // FIXME If in module environment.\n\n if (!maptalks) {\n throw new Error('Maptalks library must be included. See https://maptalks.org');\n }\n\n this._maptalks = new maptalks.Map(this.dom, {\n center: defaultCenter,\n zoom: defaultZoom,\n doubleClickZoom: false,\n fog: false // fogColor: [0, 0, 0]\n\n }); // Proxy events\n\n this._initEvents();\n}\n\nMaptalks3DLayer.prototype.setUnpainted = function () {};\n\nMaptalks3DLayer.prototype.resize = function () {\n this._maptalks.checkSize();\n};\n\nMaptalks3DLayer.prototype.getMaptalks = function () {\n return this._maptalks;\n};\n\nMaptalks3DLayer.prototype.clear = function () {};\n\nMaptalks3DLayer.prototype.refresh = function () {\n this._maptalks.checkSize();\n};\n\nvar EVENTS = ['mousedown', 'mouseup', 'click', 'dblclick', 'mousemove', 'mousewheel', 'DOMMouseScroll', 'touchstart', 'touchend', 'touchmove', 'touchcancel'];\n\nMaptalks3DLayer.prototype._initEvents = function () {\n // Event is bound on canvas container.\n var maptalksRoot = this.dom;\n this._handlers = this._handlers || {\n contextmenu: function (e) {\n e.preventDefault();\n return false;\n }\n };\n EVENTS.forEach(function (eName) {\n this._handlers[eName] = function (e) {\n var obj = {};\n\n for (var name in e) {\n obj[name] = e[name];\n }\n\n obj.bubbles = false;\n var newE = new e.constructor(e.type, obj);\n\n if (eName === 'mousewheel' || eName === 'DOMMouseScroll') {\n // maptalks listens events to different elements?\n maptalksRoot.dispatchEvent(newE);\n } else {\n maptalksRoot.firstElementChild.dispatchEvent(newE);\n }\n };\n\n this.zr.dom.addEventListener(eName, this._handlers[eName]);\n }, this); // PENDING\n\n this.zr.dom.addEventListener('contextmenu', this._handlers.contextmenu);\n};\n\nMaptalks3DLayer.prototype.dispose = function () {\n EVENTS.forEach(function (eName) {\n this.zr.dom.removeEventListener(eName, this._handlers[eName]);\n }, this);\n\n this._maptalks.remove();\n};\n\nexport default Maptalks3DLayer;","import * as echarts from 'echarts/lib/echarts';\nimport Maptalks3DLayer from './Maptalks3DLayer';\nimport SceneHelper from '../common/SceneHelper';\nimport graphicGL from '../../util/graphicGL';\nimport displayShadowGLSL from '../../util/shader/displayShadow.glsl.js';\ngraphicGL.Shader.import(displayShadowGLSL);\nexport default echarts.ComponentView.extend({\n type: 'maptalks3D',\n __ecgl__: true,\n init: function (ecModel, api) {\n this._groundMesh = new graphicGL.Mesh({\n geometry: new graphicGL.PlaneGeometry(),\n material: new graphicGL.Material({\n shader: new graphicGL.Shader({\n vertex: graphicGL.Shader.source('ecgl.displayShadow.vertex'),\n fragment: graphicGL.Shader.source('ecgl.displayShadow.fragment')\n }),\n depthMask: false\n }),\n // Render first\n renderOrder: -100,\n culling: false,\n castShadow: false,\n $ignorePicking: true,\n renderNormal: true\n });\n },\n _initMaptalksLayer: function (mapbox3DModel, api) {\n var zr = api.getZr();\n this._zrLayer = new Maptalks3DLayer('maptalks3D', zr, mapbox3DModel.get('center'), mapbox3DModel.get('zoom'));\n zr.painter.insertLayer(-1000, this._zrLayer);\n this._lightRoot = new graphicGL.Node();\n this._sceneHelper = new SceneHelper(this._lightRoot);\n\n this._sceneHelper.initLight(this._lightRoot);\n\n var maptalks = this._zrLayer.getMaptalks();\n\n var dispatchInteractAction = this._dispatchInteractAction.bind(this, api, maptalks); // PENDING\n\n\n ['zoomend', 'zooming', 'zoomstart', 'dragrotating', 'pitch', 'pitchend', 'movestart', 'moving', 'moveend', 'resize', 'touchstart', 'touchmove', 'touchend', 'animating'].forEach(function (eName) {\n maptalks.on(eName, dispatchInteractAction);\n });\n },\n render: function (maptalks3DModel, ecModel, api) {\n if (!this._zrLayer) {\n this._initMaptalksLayer(maptalks3DModel, api);\n }\n\n var mtks = this._zrLayer.getMaptalks();\n\n var urlTemplate = maptalks3DModel.get('urlTemplate');\n var baseLayer = mtks.getBaseLayer();\n\n if (urlTemplate !== this._oldUrlTemplate) {\n if (!baseLayer) {\n baseLayer = new maptalks.TileLayer('maptalks-echarts-gl-baselayer', {\n urlTemplate: urlTemplate,\n // used sequentially to help with browser parallel requests per domain limitation\n subdomains: ['a', 'b', 'c'],\n attribution: maptalks3DModel.get('attribution')\n });\n mtks.setBaseLayer(baseLayer);\n } else {\n // PENDING setOptions may not work?\n baseLayer.setOptions({\n urlTemplate: urlTemplate,\n attribution: maptalks3DModel.get('attribution')\n });\n }\n }\n\n this._oldUrlTemplate = urlTemplate;\n mtks.setCenter(maptalks3DModel.get('center'));\n mtks.setZoom(maptalks3DModel.get('zoom'), {\n animation: false\n });\n mtks.setPitch(maptalks3DModel.get('pitch'));\n mtks.setBearing(maptalks3DModel.get('bearing'));\n maptalks3DModel.setMaptalks(mtks);\n var coordSys = maptalks3DModel.coordinateSystem; // Not add to rootNode. Or light direction will be stretched by rootNode scale\n\n coordSys.viewGL.scene.add(this._lightRoot);\n coordSys.viewGL.add(this._groundMesh);\n\n this._updateGroundMesh(); // Update lights\n\n\n this._sceneHelper.setScene(coordSys.viewGL.scene);\n\n this._sceneHelper.updateLight(maptalks3DModel); // Update post effects\n\n\n coordSys.viewGL.setPostEffect(maptalks3DModel.getModel('postEffect'), api);\n coordSys.viewGL.setTemporalSuperSampling(maptalks3DModel.getModel('temporalSuperSampling'));\n this._maptalks3DModel = maptalks3DModel;\n },\n afterRender: function (maptalks3DModel, ecModel, api, layerGL) {\n var renderer = layerGL.renderer;\n\n this._sceneHelper.updateAmbientCubemap(renderer, maptalks3DModel, api);\n\n this._sceneHelper.updateSkybox(renderer, maptalks3DModel, api); // FIXME If other series changes coordinate system.\n // FIXME When doing progressive rendering.\n\n\n maptalks3DModel.coordinateSystem.viewGL.scene.traverse(function (mesh) {\n if (mesh.material) {\n mesh.material.define('fragment', 'NORMAL_UP_AXIS', 2);\n mesh.material.define('fragment', 'NORMAL_FRONT_AXIS', 1);\n }\n });\n },\n updateCamera: function (maptalks3DModel, ecModel, api, payload) {\n maptalks3DModel.coordinateSystem.setCameraOption(payload);\n\n this._updateGroundMesh();\n\n api.getZr().refresh();\n },\n _dispatchInteractAction: function (api, maptalks, maptalks3DModel) {\n api.dispatchAction({\n type: 'maptalks3DChangeCamera',\n pitch: maptalks.getPitch(),\n zoom: getMapboxZoom(maptalks.getResolution()) + 1,\n center: maptalks.getCenter().toArray(),\n bearing: maptalks.getBearing(),\n maptalks3DId: this._maptalks3DModel && this._maptalks3DModel.id\n });\n },\n _updateGroundMesh: function () {\n if (this._maptalks3DModel) {\n var coordSys = this._maptalks3DModel.coordinateSystem;\n var pt = coordSys.dataToPoint(coordSys.center);\n\n this._groundMesh.position.set(pt[0], pt[1], -0.001);\n\n var plane = new graphicGL.Plane(new graphicGL.Vector3(0, 0, 1), 0);\n var ray1 = coordSys.viewGL.camera.castRay(new graphicGL.Vector2(-1, -1));\n var ray2 = coordSys.viewGL.camera.castRay(new graphicGL.Vector2(1, 1));\n var pos0 = ray1.intersectPlane(plane);\n var pos1 = ray2.intersectPlane(plane);\n var scale = pos0.dist(pos1) / coordSys.viewGL.rootNode.scale.x;\n\n this._groundMesh.scale.set(scale, scale, 1);\n }\n },\n dispose: function (ecModel, api) {\n if (this._zrLayer) {\n this._zrLayer.dispose();\n }\n\n api.getZr().painter.delLayer(-1000);\n }\n});\nconst MAX_RES = 2 * 6378137 * Math.PI / (256 * Math.pow(2, 20));\n\nfunction getMapboxZoom(res) {\n return 19 - Math.log(res / MAX_RES) / Math.LN2;\n}","import MapService3D from '../mapServiceCommon/MapService3D';\n\nfunction Maptalks3D() {\n MapService3D.apply(this, arguments);\n this.maxPitch = 85;\n this.zoomOffset = 1;\n}\n\nMaptalks3D.prototype = new MapService3D();\nMaptalks3D.prototype.constructor = Maptalks3D;\nMaptalks3D.prototype.type = 'maptalks3D';\nexport default Maptalks3D;","import Maptalks3D from './maptalks3D/Maptalks3D';\nimport createMapService3DCreator from './mapServiceCommon/createMapService3DCreator';\nvar maptalks3DCreator = createMapService3DCreator('maptalks3D', Maptalks3D, function (maptalks3DList) {\n maptalks3DList.forEach(function (maptalks3D) {\n maptalks3D.setCameraOption(maptalks3D.model.getMaptalksCameraOption());\n });\n});\nexport default maptalks3DCreator;","// TODO ECharts GL must be imported whatever component,charts is imported.\nimport '../../echarts-gl';\nimport Maptalks3DModel from './Maptalks3DModel';\nimport Maptalks3DView from './Maptalks3DView';\nimport maptalks3DCreator from '../../coord/maptalks3DCreator';\nexport function install(registers) {\n registers.registerComponentModel(Maptalks3DModel);\n registers.registerComponentView(Maptalks3DView);\n registers.registerCoordinateSystem('maptalks3D', maptalks3DCreator);\n registers.registerAction({\n type: 'maptalks3DChangeCamera',\n event: 'maptalks3dcamerachanged',\n update: 'maptalks3D:updateCamera'\n }, function (payload, ecModel) {\n ecModel.eachComponent({\n mainType: 'maptalks3D',\n query: payload\n }, function (componentModel) {\n componentModel.setMaptalksCameraOption(payload);\n });\n });\n}","// Thanks to https://gitee.com/iverson_hu/maptalks-echarts-gl\nimport { use } from 'echarts/lib/echarts';\nimport { install } from './maptalks3D/install';\nuse(install);","import * as echarts from 'echarts/lib/echarts';\nimport glmatrix from 'claygl/src/dep/glmatrix';\nvar vec3 = glmatrix.vec3;\nvar isDimensionStacked = echarts.helper.dataStack.isDimensionStacked;\n\nfunction ifCrossZero(extent) {\n var min = extent[0];\n var max = extent[1];\n return !(min > 0 && max > 0 || min < 0 && max < 0);\n}\n\n;\n\nfunction cartesian3DLayout(seriesModel, coordSys) {\n var data = seriesModel.getData(); // var barOnPlane = seriesModel.get('onGridPlane');\n\n var barSize = seriesModel.get('barSize');\n\n if (barSize == null) {\n var size = coordSys.size;\n var barWidth;\n var barDepth;\n var xAxis = coordSys.getAxis('x');\n var yAxis = coordSys.getAxis('y');\n\n if (xAxis.type === 'category') {\n barWidth = xAxis.getBandWidth() * 0.7;\n } else {\n // PENDING\n barWidth = Math.round(size[0] / Math.sqrt(data.count())) * 0.6;\n }\n\n if (yAxis.type === 'category') {\n barDepth = yAxis.getBandWidth() * 0.7;\n } else {\n barDepth = Math.round(size[1] / Math.sqrt(data.count())) * 0.6;\n }\n\n barSize = [barWidth, barDepth];\n } else if (!echarts.util.isArray(barSize)) {\n barSize = [barSize, barSize];\n }\n\n var zAxisExtent = coordSys.getAxis('z').scale.getExtent();\n var ifZAxisCrossZero = ifCrossZero(zAxisExtent);\n var dims = ['x', 'y', 'z'].map(function (coordDimName) {\n return seriesModel.coordDimToDataDim(coordDimName)[0];\n });\n var isStacked = isDimensionStacked(data, dims[2]);\n var valueDim = isStacked ? data.getCalculationInfo('stackResultDimension') : dims[2];\n data.each(dims, function (x, y, z, idx) {\n // TODO zAxis is inversed\n // TODO On different plane.\n var stackedValue = data.get(valueDim, idx);\n var baseValue = isStacked ? stackedValue - z : ifZAxisCrossZero ? 0 : zAxisExtent[0];\n var start = coordSys.dataToPoint([x, y, baseValue]);\n var end = coordSys.dataToPoint([x, y, stackedValue]);\n var height = vec3.dist(start, end); // PENDING When zAxis is not cross zero.\n\n var dir = [0, end[1] < start[1] ? -1 : 1, 0];\n\n if (Math.abs(height) === 0) {\n // TODO\n height = 0.1;\n }\n\n var size = [barSize[0], height, barSize[1]];\n data.setItemLayout(idx, [start, dir, size]);\n });\n data.setLayout('orient', [1, 0, 0]);\n}\n\nexport default cartesian3DLayout;","export default function (data, dimX, dimY) {\n var xExtent = data.getDataExtent(dimX);\n var yExtent = data.getDataExtent(dimY); // TODO Handle one data situation\n\n var xSpan = xExtent[1] - xExtent[0] || xExtent[0];\n var ySpan = yExtent[1] - yExtent[0] || yExtent[0];\n var dimSize = 50;\n var tmp = new Uint8Array(dimSize * dimSize);\n\n for (var i = 0; i < data.count(); i++) {\n var x = data.get(dimX, i);\n var y = data.get(dimY, i);\n var xIdx = Math.floor((x - xExtent[0]) / xSpan * (dimSize - 1));\n var yIdx = Math.floor((y - yExtent[0]) / ySpan * (dimSize - 1));\n var idx = yIdx * dimSize + xIdx;\n tmp[idx] = tmp[idx] || 1;\n }\n\n var filledCount = 0;\n\n for (var i = 0; i < tmp.length; i++) {\n if (tmp[i]) {\n filledCount++;\n }\n }\n\n return filledCount / tmp.length;\n}\n;","import * as echarts from 'echarts/lib/echarts';\nimport Vector3 from 'claygl/src/math/Vector3';\nimport glmatrix from 'claygl/src/dep/glmatrix';\nimport cartesian3DLayout from './cartesian3DLayout';\nimport evaluateBarSparseness from './evaluateBarSparseness';\nvar vec3 = glmatrix.vec3;\nvar isDimensionStacked = echarts.helper.dataStack.isDimensionStacked;\n\nfunction globeLayout(seriesModel, coordSys) {\n var data = seriesModel.getData();\n var barMinHeight = seriesModel.get('minHeight') || 0;\n var barSize = seriesModel.get('barSize');\n var dims = ['lng', 'lat', 'alt'].map(function (coordDimName) {\n return seriesModel.coordDimToDataDim(coordDimName)[0];\n });\n\n if (barSize == null) {\n var perimeter = coordSys.radius * Math.PI;\n var fillRatio = evaluateBarSparseness(data, dims[0], dims[1]);\n barSize = [perimeter / Math.sqrt(data.count() / fillRatio), perimeter / Math.sqrt(data.count() / fillRatio)];\n } else if (!echarts.util.isArray(barSize)) {\n barSize = [barSize, barSize];\n }\n\n var valueDim = getValueDimension(data, dims);\n data.each(dims, function (lng, lat, val, idx) {\n var stackedValue = data.get(valueDim.dimension, idx);\n var baseValue = valueDim.isStacked ? stackedValue - val : coordSys.altitudeAxis.scale.getExtent()[0]; // TODO Stacked with minHeight.\n\n var height = Math.max(coordSys.altitudeAxis.dataToCoord(val), barMinHeight);\n var start = coordSys.dataToPoint([lng, lat, baseValue]);\n var end = coordSys.dataToPoint([lng, lat, stackedValue]);\n var dir = vec3.sub([], end, start);\n vec3.normalize(dir, dir);\n var size = [barSize[0], height, barSize[1]];\n data.setItemLayout(idx, [start, dir, size]);\n });\n data.setLayout('orient', Vector3.UP.array);\n}\n\nfunction geo3DLayout(seriesModel, coordSys) {\n var data = seriesModel.getData();\n var barSize = seriesModel.get('barSize');\n var barMinHeight = seriesModel.get('minHeight') || 0;\n var dims = ['lng', 'lat', 'alt'].map(function (coordDimName) {\n return seriesModel.coordDimToDataDim(coordDimName)[0];\n });\n\n if (barSize == null) {\n var size = Math.min(coordSys.size[0], coordSys.size[2]);\n var fillRatio = evaluateBarSparseness(data, dims[0], dims[1]);\n barSize = [size / Math.sqrt(data.count() / fillRatio), size / Math.sqrt(data.count() / fillRatio)];\n } else if (!echarts.util.isArray(barSize)) {\n barSize = [barSize, barSize];\n }\n\n var dir = [0, 1, 0];\n var valueDim = getValueDimension(data, dims);\n data.each(dims, function (lng, lat, val, idx) {\n var stackedValue = data.get(valueDim.dimension, idx);\n var baseValue = valueDim.isStacked ? stackedValue - val : coordSys.altitudeAxis.scale.getExtent()[0];\n var height = Math.max(coordSys.altitudeAxis.dataToCoord(val), barMinHeight);\n var start = coordSys.dataToPoint([lng, lat, baseValue]);\n var size = [barSize[0], height, barSize[1]];\n data.setItemLayout(idx, [start, dir, size]);\n });\n data.setLayout('orient', [1, 0, 0]);\n}\n\nfunction mapService3DLayout(seriesModel, coordSys) {\n var data = seriesModel.getData();\n var dimLng = seriesModel.coordDimToDataDim('lng')[0];\n var dimLat = seriesModel.coordDimToDataDim('lat')[0];\n var dimAlt = seriesModel.coordDimToDataDim('alt')[0];\n var barSize = seriesModel.get('barSize');\n var barMinHeight = seriesModel.get('minHeight') || 0;\n\n if (barSize == null) {\n var xExtent = data.getDataExtent(dimLng);\n var yExtent = data.getDataExtent(dimLat);\n var corner0 = coordSys.dataToPoint([xExtent[0], yExtent[0]]);\n var corner1 = coordSys.dataToPoint([xExtent[1], yExtent[1]]);\n var size = Math.min(Math.abs(corner0[0] - corner1[0]), Math.abs(corner0[1] - corner1[1])) || 1;\n var fillRatio = evaluateBarSparseness(data, dimLng, dimLat); // PENDING, data density\n\n barSize = [size / Math.sqrt(data.count() / fillRatio), size / Math.sqrt(data.count() / fillRatio)];\n } else {\n if (!echarts.util.isArray(barSize)) {\n barSize = [barSize, barSize];\n }\n\n barSize[0] /= coordSys.getScale() / 16;\n barSize[1] /= coordSys.getScale() / 16;\n }\n\n var dir = [0, 0, 1];\n var dims = [dimLng, dimLat, dimAlt];\n var valueDim = getValueDimension(data, dims);\n data.each(dims, function (lng, lat, val, idx) {\n var stackedValue = data.get(valueDim.dimension, idx);\n var baseValue = valueDim.isStacked ? stackedValue - val : 0;\n var start = coordSys.dataToPoint([lng, lat, baseValue]);\n var end = coordSys.dataToPoint([lng, lat, stackedValue]);\n var height = Math.max(end[2] - start[2], barMinHeight);\n var size = [barSize[0], height, barSize[1]];\n data.setItemLayout(idx, [start, dir, size]);\n });\n data.setLayout('orient', [1, 0, 0]);\n}\n\nfunction getValueDimension(data, dataDims) {\n var isStacked = isDimensionStacked(data, dataDims[2]);\n return {\n dimension: isStacked ? data.getCalculationInfo('stackResultDimension') : dataDims[2],\n isStacked: isStacked\n };\n}\n\nexport default function registerBarLayout(registers) {\n registers.registerLayout(function (ecModel, api) {\n ecModel.eachSeriesByType('bar3D', function (seriesModel) {\n var coordSys = seriesModel.coordinateSystem;\n var coordSysType = coordSys && coordSys.type;\n\n if (coordSysType === 'globe') {\n globeLayout(seriesModel, coordSys);\n } else if (coordSysType === 'cartesian3D') {\n cartesian3DLayout(seriesModel, coordSys);\n } else if (coordSysType === 'geo3D') {\n geo3DLayout(seriesModel, coordSys);\n } else if (coordSysType === 'mapbox3D' || coordSysType === 'maptalks3D') {\n mapService3DLayout(seriesModel, coordSys);\n } else {\n if (process.env.NODE_ENV !== 'production') {\n if (!coordSys) {\n throw new Error('bar3D doesn\\'t have coordinate system.');\n } else {\n throw new Error('bar3D doesn\\'t support coordinate system ' + coordSys.type);\n }\n }\n }\n });\n });\n}","import * as echarts from 'echarts/lib/echarts';\nvar formatUtil = {};\n\nformatUtil.getFormattedLabel = function (seriesModel, dataIndex, status, dataType, dimIndex) {\n status = status || 'normal';\n var data = seriesModel.getData(dataType);\n var itemModel = data.getItemModel(dataIndex);\n var params = seriesModel.getDataParams(dataIndex, dataType);\n\n if (dimIndex != null && params.value instanceof Array) {\n params.value = params.value[dimIndex];\n }\n\n var formatter = itemModel.get(status === 'normal' ? ['label', 'formatter'] : ['emphasis', 'label', 'formatter']);\n\n if (formatter == null) {\n formatter = itemModel.get(['label', 'formatter']);\n }\n\n var text;\n\n if (typeof formatter === 'function') {\n params.status = status;\n text = formatter(params);\n } else if (typeof formatter === 'string') {\n text = echarts.format.formatTpl(formatter, params);\n }\n\n return text;\n};\n/**\n * If value is not array, then convert it to array.\n * @param {*} value\n * @return {Array} [value] or value\n */\n\n\nformatUtil.normalizeToArray = function (value) {\n return value instanceof Array ? value : value == null ? [] : [value];\n};\n\nexport default formatUtil;","import * as echarts from 'echarts/lib/echarts';\nimport { getItemVisualColor } from '../../util/visual';\n\nfunction otherDimToDataDim(data, otherDim) {\n var dataDim = [];\n echarts.util.each(data.dimensions, function (dimName) {\n var dimItem = data.getDimensionInfo(dimName);\n var otherDims = dimItem.otherDims;\n var dimIndex = otherDims[otherDim];\n\n if (dimIndex != null && dimIndex !== false) {\n dataDim[dimIndex] = dimItem.name;\n }\n });\n return dataDim;\n}\n\nexport default function (seriesModel, dataIndex, multipleSeries) {\n function formatArrayValue(value) {\n var vertially = true;\n var result = [];\n var tooltipDims = otherDimToDataDim(data, 'tooltip');\n tooltipDims.length ? echarts.util.each(tooltipDims, function (dimIdx) {\n setEachItem(data.get(dimIdx, dataIndex), dimIdx);\n }) // By default, all dims is used on tooltip.\n : echarts.util.each(value, setEachItem);\n\n function setEachItem(val, dimIdx) {\n var dimInfo = data.getDimensionInfo(dimIdx); // If `dimInfo.tooltip` is not set, show tooltip.\n\n if (!dimInfo || dimInfo.otherDims.tooltip === false) {\n return;\n }\n\n var dimType = dimInfo.type;\n var valStr = (vertially ? '- ' + (dimInfo.tooltipName || dimInfo.name) + ': ' : '') + (dimType === 'ordinal' ? val + '' : dimType === 'time' ? multipleSeries ? '' : echarts.format.formatTime('yyyy/MM/dd hh:mm:ss', val) : echarts.format.addCommas(val));\n valStr && result.push(echarts.format.encodeHTML(valStr));\n }\n\n return (vertially ? '
' : '') + result.join(vertially ? '
' : ', ');\n }\n\n var data = seriesModel.getData();\n var value = seriesModel.getRawValue(dataIndex);\n var formattedValue = echarts.util.isArray(value) ? formatArrayValue(value) : echarts.format.encodeHTML(echarts.format.addCommas(value));\n var name = data.getName(dataIndex);\n var color = getItemVisualColor(data, dataIndex);\n\n if (echarts.util.isObject(color) && color.colorStops) {\n color = (color.colorStops[0] || {}).color;\n }\n\n color = color || 'transparent';\n var colorEl = echarts.format.getTooltipMarker(color);\n var seriesName = seriesModel.name; // FIXME\n\n if (seriesName === '\\0-') {\n // Not show '-'\n seriesName = '';\n }\n\n seriesName = seriesName ? echarts.format.encodeHTML(seriesName) + (!multipleSeries ? '
' : ': ') : '';\n return !multipleSeries ? seriesName + colorEl + (name ? echarts.format.encodeHTML(name) + ': ' + formattedValue : formattedValue) : colorEl + seriesName + formattedValue;\n}\n;","import * as echarts from 'echarts/lib/echarts';\nexport default function (seriesModel, dims, source) {\n source = source || seriesModel.getSource();\n var coordSysDimensions = dims || echarts.getCoordinateSystemDimensions(seriesModel.get('coordinateSystem')) || ['x', 'y', 'z'];\n var dimensions = echarts.helper.createDimensions(source, {\n dimensionsDefine: source.dimensionsDefine || seriesModel.get('dimensions'),\n encodeDefine: source.encodeDefine || seriesModel.get('encode'),\n coordDimensions: coordSysDimensions.map(function (dim) {\n var axis3DModel = seriesModel.getReferringComponents(dim + 'Axis3D').models[0];\n return {\n type: axis3DModel && axis3DModel.get('type') === 'category' ? 'ordinal' : 'float',\n name: dim // Find stackable dimension. Which will represent value.\n // stackable: dim === 'z'\n\n };\n })\n });\n\n if (seriesModel.get('coordinateSystem') === 'cartesian3D') {\n dimensions.forEach(function (dimInfo) {\n if (coordSysDimensions.indexOf(dimInfo.coordDim) >= 0) {\n var axis3DModel = seriesModel.getReferringComponents(dimInfo.coordDim + 'Axis3D').models[0];\n\n if (axis3DModel && axis3DModel.get('type') === 'category') {\n dimInfo.ordinalMeta = axis3DModel.getOrdinalMeta();\n }\n }\n });\n }\n\n var stackCalculationInfo = echarts.helper.dataStack.enableDataStack( // Only support 'z' and `byIndex` now.\n seriesModel, dimensions, {\n byIndex: true,\n stackedCoordDimension: 'z'\n });\n var data = new echarts.List(dimensions, seriesModel);\n data.setCalculationInfo(stackCalculationInfo);\n data.initData(source);\n return data;\n}","import * as echarts from 'echarts/lib/echarts';\nimport componentShadingMixin from '../../component/common/componentShadingMixin';\nimport formatUtil from '../../util/format';\nimport formatTooltip from '../common/formatTooltip';\nimport createList from '../common/createList';\nvar Bar3DSeries = echarts.SeriesModel.extend({\n type: 'series.bar3D',\n dependencies: ['globe'],\n visualStyleAccessPathvisu: 'itemStyle',\n getInitialData: function (option, ecModel) {\n return createList(this);\n },\n getFormattedLabel: function (dataIndex, status, dataType, dimIndex) {\n var text = formatUtil.getFormattedLabel(this, dataIndex, status, dataType, dimIndex);\n\n if (text == null) {\n text = this.getData().get('z', dataIndex);\n }\n\n return text;\n },\n formatTooltip: function (dataIndex) {\n return formatTooltip(this, dataIndex);\n },\n defaultOption: {\n coordinateSystem: 'cartesian3D',\n globeIndex: 0,\n grid3DIndex: 0,\n zlevel: -10,\n // bevelSize, 0 has no bevel\n bevelSize: 0,\n // higher is smoother\n bevelSmoothness: 2,\n // Bar width and depth\n // barSize: [1, 1],\n // On grid plane when coordinateSystem is cartesian3D\n onGridPlane: 'xy',\n // Shading of globe\n shading: 'color',\n minHeight: 0,\n itemStyle: {\n opacity: 1\n },\n label: {\n show: false,\n distance: 2,\n textStyle: {\n fontSize: 14,\n color: '#000',\n backgroundColor: 'rgba(255,255,255,0.7)',\n padding: 3,\n borderRadius: 3\n }\n },\n emphasis: {\n label: {\n show: true\n }\n },\n animationDurationUpdate: 500\n }\n});\necharts.util.merge(Bar3DSeries.prototype, componentShadingMixin);\nexport default Bar3DSeries;","/**\n * Geometry collecting bars data\n *\n * @module echarts-gl/chart/bars/BarsGeometry\n * @author Yi Shen(http://github.com/pissang)\n */\nimport * as echarts from 'echarts/lib/echarts';\nimport dynamicConvertMixin from './dynamicConvertMixin';\nimport trianglesSortMixin from './trianglesSortMixin';\nimport Geometry from 'claygl/src/Geometry';\nimport glMatrix from 'claygl/src/dep/glmatrix';\nvar vec3 = glMatrix.vec3;\nvar mat3 = glMatrix.mat3;\n/**\n * @constructor\n * @alias module:echarts-gl/chart/bars/BarsGeometry\n * @extends clay.Geometry\n */\n\nvar BarsGeometry = Geometry.extend(function () {\n return {\n attributes: {\n position: new Geometry.Attribute('position', 'float', 3, 'POSITION'),\n normal: new Geometry.Attribute('normal', 'float', 3, 'NORMAL'),\n color: new Geometry.Attribute('color', 'float', 4, 'COLOR'),\n prevPosition: new Geometry.Attribute('prevPosition', 'float', 3),\n prevNormal: new Geometry.Attribute('prevNormal', 'float', 3)\n },\n dynamic: true,\n enableNormal: false,\n bevelSize: 1,\n bevelSegments: 0,\n // Map from vertexIndex to dataIndex.\n _dataIndices: null,\n _vertexOffset: 0,\n _triangleOffset: 0\n };\n},\n/** @lends module:echarts-gl/chart/bars/BarsGeometry.prototype */\n{\n resetOffset: function () {\n this._vertexOffset = 0;\n this._triangleOffset = 0;\n },\n setBarCount: function (barCount) {\n var enableNormal = this.enableNormal;\n var vertexCount = this.getBarVertexCount() * barCount;\n var triangleCount = this.getBarTriangleCount() * barCount;\n\n if (this.vertexCount !== vertexCount) {\n this.attributes.position.init(vertexCount);\n\n if (enableNormal) {\n this.attributes.normal.init(vertexCount);\n } else {\n this.attributes.normal.value = null;\n }\n\n this.attributes.color.init(vertexCount);\n }\n\n if (this.triangleCount !== triangleCount) {\n this.indices = vertexCount > 0xffff ? new Uint32Array(triangleCount * 3) : new Uint16Array(triangleCount * 3);\n this._dataIndices = new Uint32Array(vertexCount);\n }\n },\n getBarVertexCount: function () {\n var bevelSegments = this.bevelSize > 0 ? this.bevelSegments : 0;\n return bevelSegments > 0 ? this._getBevelBarVertexCount(bevelSegments) : this.enableNormal ? 24 : 8;\n },\n getBarTriangleCount: function () {\n var bevelSegments = this.bevelSize > 0 ? this.bevelSegments : 0;\n return bevelSegments > 0 ? this._getBevelBarTriangleCount(bevelSegments) : 12;\n },\n _getBevelBarVertexCount: function (bevelSegments) {\n return (bevelSegments + 1) * 4 * (bevelSegments + 1) * 2;\n },\n _getBevelBarTriangleCount: function (bevelSegments) {\n var widthSegments = bevelSegments * 4 + 3;\n var heightSegments = bevelSegments * 2 + 1;\n return (widthSegments + 1) * heightSegments * 2 + 4;\n },\n setColor: function (idx, color) {\n var vertexCount = this.getBarVertexCount();\n var start = vertexCount * idx;\n var end = vertexCount * (idx + 1);\n\n for (var i = start; i < end; i++) {\n this.attributes.color.set(i, color);\n }\n\n this.dirtyAttribute('color');\n },\n\n /**\n * Get dataIndex of vertex.\n * @param {number} vertexIndex\n */\n getDataIndexOfVertex: function (vertexIndex) {\n return this._dataIndices ? this._dataIndices[vertexIndex] : null;\n },\n\n /**\n * Add a bar\n * @param {Array.} start\n * @param {Array.} end\n * @param {Array.} orient right direction\n * @param {Array.} size size on x and z\n * @param {Array.} color\n */\n addBar: function () {\n var v3Create = vec3.create;\n var v3ScaleAndAdd = vec3.scaleAndAdd;\n var end = v3Create();\n var px = v3Create();\n var py = v3Create();\n var pz = v3Create();\n var nx = v3Create();\n var ny = v3Create();\n var nz = v3Create();\n var pts = [];\n var normals = [];\n\n for (var i = 0; i < 8; i++) {\n pts[i] = v3Create();\n }\n\n var cubeFaces4 = [// PX\n [0, 1, 5, 4], // NX\n [2, 3, 7, 6], // PY\n [4, 5, 6, 7], // NY\n [3, 2, 1, 0], // PZ\n [0, 4, 7, 3], // NZ\n [1, 2, 6, 5]];\n var face4To3 = [0, 1, 2, 0, 2, 3];\n var cubeFaces3 = [];\n\n for (var i = 0; i < cubeFaces4.length; i++) {\n var face4 = cubeFaces4[i];\n\n for (var j = 0; j < 2; j++) {\n var face = [];\n\n for (var k = 0; k < 3; k++) {\n face.push(face4[face4To3[j * 3 + k]]);\n }\n\n cubeFaces3.push(face);\n }\n }\n\n return function (start, dir, leftDir, size, color, dataIndex) {\n // Use vertex, triangle maybe sorted.\n var startVertex = this._vertexOffset;\n\n if (this.bevelSize > 0 && this.bevelSegments > 0) {\n this._addBevelBar(start, dir, leftDir, size, this.bevelSize, this.bevelSegments, color);\n } else {\n vec3.copy(py, dir);\n vec3.normalize(py, py); // x * y => z\n\n vec3.cross(pz, leftDir, py);\n vec3.normalize(pz, pz); // y * z => x\n\n vec3.cross(px, py, pz);\n vec3.normalize(pz, pz);\n vec3.negate(nx, px);\n vec3.negate(ny, py);\n vec3.negate(nz, pz);\n v3ScaleAndAdd(pts[0], start, px, size[0] / 2);\n v3ScaleAndAdd(pts[0], pts[0], pz, size[2] / 2);\n v3ScaleAndAdd(pts[1], start, px, size[0] / 2);\n v3ScaleAndAdd(pts[1], pts[1], nz, size[2] / 2);\n v3ScaleAndAdd(pts[2], start, nx, size[0] / 2);\n v3ScaleAndAdd(pts[2], pts[2], nz, size[2] / 2);\n v3ScaleAndAdd(pts[3], start, nx, size[0] / 2);\n v3ScaleAndAdd(pts[3], pts[3], pz, size[2] / 2);\n v3ScaleAndAdd(end, start, py, size[1]);\n v3ScaleAndAdd(pts[4], end, px, size[0] / 2);\n v3ScaleAndAdd(pts[4], pts[4], pz, size[2] / 2);\n v3ScaleAndAdd(pts[5], end, px, size[0] / 2);\n v3ScaleAndAdd(pts[5], pts[5], nz, size[2] / 2);\n v3ScaleAndAdd(pts[6], end, nx, size[0] / 2);\n v3ScaleAndAdd(pts[6], pts[6], nz, size[2] / 2);\n v3ScaleAndAdd(pts[7], end, nx, size[0] / 2);\n v3ScaleAndAdd(pts[7], pts[7], pz, size[2] / 2);\n var attributes = this.attributes;\n\n if (this.enableNormal) {\n normals[0] = px;\n normals[1] = nx;\n normals[2] = py;\n normals[3] = ny;\n normals[4] = pz;\n normals[5] = nz;\n var vertexOffset = this._vertexOffset;\n\n for (var i = 0; i < cubeFaces4.length; i++) {\n var idx3 = this._triangleOffset * 3;\n\n for (var k = 0; k < 6; k++) {\n this.indices[idx3++] = vertexOffset + face4To3[k];\n }\n\n vertexOffset += 4;\n this._triangleOffset += 2;\n }\n\n for (var i = 0; i < cubeFaces4.length; i++) {\n var normal = normals[i];\n\n for (var k = 0; k < 4; k++) {\n var idx = cubeFaces4[i][k];\n attributes.position.set(this._vertexOffset, pts[idx]);\n attributes.normal.set(this._vertexOffset, normal);\n attributes.color.set(this._vertexOffset++, color);\n }\n }\n } else {\n for (var i = 0; i < cubeFaces3.length; i++) {\n var idx3 = this._triangleOffset * 3;\n\n for (var k = 0; k < 3; k++) {\n this.indices[idx3 + k] = cubeFaces3[i][k] + this._vertexOffset;\n }\n\n this._triangleOffset++;\n }\n\n for (var i = 0; i < pts.length; i++) {\n attributes.position.set(this._vertexOffset, pts[i]);\n attributes.color.set(this._vertexOffset++, color);\n }\n }\n }\n\n var endVerex = this._vertexOffset;\n\n for (var i = startVertex; i < endVerex; i++) {\n this._dataIndices[i] = dataIndex;\n }\n };\n }(),\n\n /**\n * Add a bar with bevel\n * @param {Array.} start\n * @param {Array.} end\n * @param {Array.} orient right direction\n * @param {Array.} size size on x and z\n * @param {number} bevelSize\n * @param {number} bevelSegments\n * @param {Array.} color\n */\n _addBevelBar: function () {\n var px = vec3.create();\n var py = vec3.create();\n var pz = vec3.create();\n var rotateMat = mat3.create();\n var bevelStartSize = [];\n var xOffsets = [1, -1, -1, 1];\n var zOffsets = [1, 1, -1, -1];\n var yOffsets = [2, 0];\n return function (start, dir, leftDir, size, bevelSize, bevelSegments, color) {\n vec3.copy(py, dir);\n vec3.normalize(py, py); // x * y => z\n\n vec3.cross(pz, leftDir, py);\n vec3.normalize(pz, pz); // y * z => x\n\n vec3.cross(px, py, pz);\n vec3.normalize(pz, pz);\n rotateMat[0] = px[0];\n rotateMat[1] = px[1];\n rotateMat[2] = px[2];\n rotateMat[3] = py[0];\n rotateMat[4] = py[1];\n rotateMat[5] = py[2];\n rotateMat[6] = pz[0];\n rotateMat[7] = pz[1];\n rotateMat[8] = pz[2];\n bevelSize = Math.min(size[0], size[2]) / 2 * bevelSize;\n\n for (var i = 0; i < 3; i++) {\n bevelStartSize[i] = Math.max(size[i] - bevelSize * 2, 0);\n }\n\n var rx = (size[0] - bevelStartSize[0]) / 2;\n var ry = (size[1] - bevelStartSize[1]) / 2;\n var rz = (size[2] - bevelStartSize[2]) / 2;\n var pos = [];\n var normal = [];\n var vertexOffset = this._vertexOffset;\n var endIndices = [];\n\n for (var i = 0; i < 2; i++) {\n endIndices[i] = endIndices[i] = [];\n\n for (var m = 0; m <= bevelSegments; m++) {\n for (var j = 0; j < 4; j++) {\n if (m === 0 && i === 0 || i === 1 && m === bevelSegments) {\n endIndices[i].push(vertexOffset);\n }\n\n for (var n = 0; n <= bevelSegments; n++) {\n var phi = n / bevelSegments * Math.PI / 2 + Math.PI / 2 * j;\n var theta = m / bevelSegments * Math.PI / 2 + Math.PI / 2 * i; // var r = rx < ry ? (rz < rx ? rz : rx) : (rz < ry ? rz : ry);\n\n normal[0] = rx * Math.cos(phi) * Math.sin(theta);\n normal[1] = ry * Math.cos(theta);\n normal[2] = rz * Math.sin(phi) * Math.sin(theta);\n pos[0] = normal[0] + xOffsets[j] * bevelStartSize[0] / 2;\n pos[1] = normal[1] + ry + yOffsets[i] * bevelStartSize[1] / 2;\n pos[2] = normal[2] + zOffsets[j] * bevelStartSize[2] / 2; // Normal is not right if rx, ry, rz not equal.\n\n if (!(Math.abs(rx - ry) < 1e-6 && Math.abs(ry - rz) < 1e-6)) {\n normal[0] /= rx * rx;\n normal[1] /= ry * ry;\n normal[2] /= rz * rz;\n }\n\n vec3.normalize(normal, normal);\n vec3.transformMat3(pos, pos, rotateMat);\n vec3.transformMat3(normal, normal, rotateMat);\n vec3.add(pos, pos, start);\n this.attributes.position.set(vertexOffset, pos);\n\n if (this.enableNormal) {\n this.attributes.normal.set(vertexOffset, normal);\n }\n\n this.attributes.color.set(vertexOffset, color);\n vertexOffset++;\n }\n }\n }\n }\n\n var widthSegments = bevelSegments * 4 + 3;\n var heightSegments = bevelSegments * 2 + 1;\n var len = widthSegments + 1;\n\n for (var j = 0; j < heightSegments; j++) {\n for (var i = 0; i <= widthSegments; i++) {\n var i2 = j * len + i + this._vertexOffset;\n var i1 = j * len + (i + 1) % len + this._vertexOffset;\n var i4 = (j + 1) * len + (i + 1) % len + this._vertexOffset;\n var i3 = (j + 1) * len + i + this._vertexOffset;\n this.setTriangleIndices(this._triangleOffset++, [i4, i2, i1]);\n this.setTriangleIndices(this._triangleOffset++, [i4, i3, i2]);\n }\n } // Close top and bottom\n\n\n this.setTriangleIndices(this._triangleOffset++, [endIndices[0][0], endIndices[0][2], endIndices[0][1]]);\n this.setTriangleIndices(this._triangleOffset++, [endIndices[0][0], endIndices[0][3], endIndices[0][2]]);\n this.setTriangleIndices(this._triangleOffset++, [endIndices[1][0], endIndices[1][1], endIndices[1][2]]);\n this.setTriangleIndices(this._triangleOffset++, [endIndices[1][0], endIndices[1][2], endIndices[1][3]]);\n this._vertexOffset = vertexOffset;\n };\n }()\n});\necharts.util.defaults(BarsGeometry.prototype, dynamicConvertMixin);\necharts.util.defaults(BarsGeometry.prototype, trianglesSortMixin);\nexport default BarsGeometry;","import * as echarts from 'echarts/lib/echarts';\nimport graphicGL from '../../util/graphicGL';\nimport retrieve from '../../util/retrieve';\nimport format from '../../util/format';\nimport BarsGeometry from '../../util/geometry/Bars3DGeometry';\nimport LabelsBuilder from '../../component/common/LabelsBuilder';\nimport glmatrix from 'claygl/src/dep/glmatrix';\nimport { getItemVisualColor, getItemVisualOpacity } from '../../util/visual';\nvar vec3 = glmatrix.vec3;\nexport default echarts.ChartView.extend({\n type: 'bar3D',\n __ecgl__: true,\n init: function (ecModel, api) {\n this.groupGL = new graphicGL.Node();\n this._api = api;\n this._labelsBuilder = new LabelsBuilder(256, 256, api);\n var self = this;\n\n this._labelsBuilder.getLabelPosition = function (dataIndex, position, distance) {\n if (self._data) {\n var layout = self._data.getItemLayout(dataIndex);\n\n var start = layout[0];\n var dir = layout[1];\n var height = layout[2][1];\n return vec3.scaleAndAdd([], start, dir, distance + height);\n } else {\n return [0, 0];\n }\n }; // Give a large render order.\n\n\n this._labelsBuilder.getMesh().renderOrder = 100;\n },\n render: function (seriesModel, ecModel, api) {\n // Swap barMesh\n var tmp = this._prevBarMesh;\n this._prevBarMesh = this._barMesh;\n this._barMesh = tmp;\n\n if (!this._barMesh) {\n this._barMesh = new graphicGL.Mesh({\n geometry: new BarsGeometry(),\n shadowDepthMaterial: new graphicGL.Material({\n shader: new graphicGL.Shader(graphicGL.Shader.source('ecgl.sm.depth.vertex'), graphicGL.Shader.source('ecgl.sm.depth.fragment'))\n }),\n // Only cartesian3D enable culling\n // FIXME Performance\n culling: seriesModel.coordinateSystem.type === 'cartesian3D',\n // Render after axes\n renderOrder: 10,\n // Render normal in normal pass\n renderNormal: true\n });\n }\n\n this.groupGL.remove(this._prevBarMesh);\n this.groupGL.add(this._barMesh);\n this.groupGL.add(this._labelsBuilder.getMesh());\n var coordSys = seriesModel.coordinateSystem;\n\n this._doRender(seriesModel, api);\n\n if (coordSys && coordSys.viewGL) {\n coordSys.viewGL.add(this.groupGL);\n var methodName = coordSys.viewGL.isLinearSpace() ? 'define' : 'undefine';\n\n this._barMesh.material[methodName]('fragment', 'SRGB_DECODE');\n }\n\n this._data = seriesModel.getData();\n\n this._labelsBuilder.updateData(this._data);\n\n this._labelsBuilder.updateLabels();\n\n this._updateAnimation(seriesModel);\n },\n _updateAnimation: function (seriesModel) {\n graphicGL.updateVertexAnimation([['prevPosition', 'position'], ['prevNormal', 'normal']], this._prevBarMesh, this._barMesh, seriesModel);\n },\n _doRender: function (seriesModel, api) {\n var data = seriesModel.getData();\n var shading = seriesModel.get('shading');\n var enableNormal = shading !== 'color';\n var self = this;\n var barMesh = this._barMesh;\n var shadingPrefix = 'ecgl.' + shading;\n\n if (!barMesh.material || barMesh.material.shader.name !== shadingPrefix) {\n barMesh.material = graphicGL.createMaterial(shadingPrefix, ['VERTEX_COLOR']);\n }\n\n graphicGL.setMaterialFromModel(shading, barMesh.material, seriesModel, api);\n barMesh.geometry.enableNormal = enableNormal;\n barMesh.geometry.resetOffset(); // Bevel settings\n\n var bevelSize = seriesModel.get('bevelSize');\n var bevelSegments = seriesModel.get('bevelSmoothness');\n barMesh.geometry.bevelSegments = bevelSegments;\n barMesh.geometry.bevelSize = bevelSize;\n var colorArr = [];\n var vertexColors = new Float32Array(data.count() * 4);\n var colorOffset = 0;\n var barCount = 0;\n var hasTransparent = false;\n data.each(function (idx) {\n if (!data.hasValue(idx)) {\n return;\n }\n\n var color = getItemVisualColor(data, idx);\n var opacity = getItemVisualOpacity(data, idx);\n\n if (opacity == null) {\n opacity = 1;\n }\n\n graphicGL.parseColor(color, colorArr);\n colorArr[3] *= opacity;\n vertexColors[colorOffset++] = colorArr[0];\n vertexColors[colorOffset++] = colorArr[1];\n vertexColors[colorOffset++] = colorArr[2];\n vertexColors[colorOffset++] = colorArr[3];\n\n if (colorArr[3] > 0) {\n barCount++;\n\n if (colorArr[3] < 0.99) {\n hasTransparent = true;\n }\n }\n });\n barMesh.geometry.setBarCount(barCount);\n var orient = data.getLayout('orient'); // Map of dataIndex and barIndex.\n\n var barIndexOfData = this._barIndexOfData = new Int32Array(data.count());\n var barCount = 0;\n data.each(function (idx) {\n if (!data.hasValue(idx)) {\n barIndexOfData[idx] = -1;\n return;\n }\n\n var layout = data.getItemLayout(idx);\n var start = layout[0];\n var dir = layout[1];\n var size = layout[2];\n var idx4 = idx * 4;\n colorArr[0] = vertexColors[idx4++];\n colorArr[1] = vertexColors[idx4++];\n colorArr[2] = vertexColors[idx4++];\n colorArr[3] = vertexColors[idx4++];\n\n if (colorArr[3] > 0) {\n self._barMesh.geometry.addBar(start, dir, orient, size, colorArr, idx);\n\n barIndexOfData[idx] = barCount++;\n }\n });\n barMesh.geometry.dirty();\n barMesh.geometry.updateBoundingBox();\n var material = barMesh.material;\n material.transparent = hasTransparent;\n material.depthMask = !hasTransparent;\n barMesh.geometry.sortTriangles = hasTransparent;\n\n this._initHandler(seriesModel, api);\n },\n _initHandler: function (seriesModel, api) {\n var data = seriesModel.getData();\n var barMesh = this._barMesh;\n var isCartesian3D = seriesModel.coordinateSystem.type === 'cartesian3D';\n barMesh.seriesIndex = seriesModel.seriesIndex;\n var lastDataIndex = -1;\n barMesh.off('mousemove');\n barMesh.off('mouseout');\n barMesh.on('mousemove', function (e) {\n var dataIndex = barMesh.geometry.getDataIndexOfVertex(e.triangle[0]);\n\n if (dataIndex !== lastDataIndex) {\n this._downplay(lastDataIndex);\n\n this._highlight(dataIndex);\n\n this._labelsBuilder.updateLabels([dataIndex]);\n\n if (isCartesian3D) {\n api.dispatchAction({\n type: 'grid3DShowAxisPointer',\n value: [data.get('x', dataIndex), data.get('y', dataIndex), data.get('z', dataIndex, true)]\n });\n }\n }\n\n lastDataIndex = dataIndex;\n barMesh.dataIndex = dataIndex;\n }, this);\n barMesh.on('mouseout', function (e) {\n this._downplay(lastDataIndex);\n\n this._labelsBuilder.updateLabels();\n\n lastDataIndex = -1;\n barMesh.dataIndex = -1;\n\n if (isCartesian3D) {\n api.dispatchAction({\n type: 'grid3DHideAxisPointer'\n });\n }\n }, this);\n },\n _highlight: function (dataIndex) {\n var data = this._data;\n\n if (!data) {\n return;\n }\n\n var barIndex = this._barIndexOfData[dataIndex];\n\n if (barIndex < 0) {\n return;\n }\n\n var itemModel = data.getItemModel(dataIndex);\n var emphasisItemStyleModel = itemModel.getModel('emphasis.itemStyle');\n var emphasisColor = emphasisItemStyleModel.get('color');\n var emphasisOpacity = emphasisItemStyleModel.get('opacity');\n\n if (emphasisColor == null) {\n var color = getItemVisualColor(data, dataIndex);\n emphasisColor = echarts.color.lift(color, -0.4);\n }\n\n if (emphasisOpacity == null) {\n emphasisOpacity = getItemVisualOpacity(data, dataIndex);\n }\n\n var colorArr = graphicGL.parseColor(emphasisColor);\n colorArr[3] *= emphasisOpacity;\n\n this._barMesh.geometry.setColor(barIndex, colorArr);\n\n this._api.getZr().refresh();\n },\n _downplay: function (dataIndex) {\n var data = this._data;\n\n if (!data) {\n return;\n }\n\n var barIndex = this._barIndexOfData[dataIndex];\n\n if (barIndex < 0) {\n return;\n }\n\n var color = getItemVisualColor(data, dataIndex);\n var opacity = getItemVisualOpacity(data, dataIndex);\n var colorArr = graphicGL.parseColor(color);\n colorArr[3] *= opacity;\n\n this._barMesh.geometry.setColor(barIndex, colorArr);\n\n this._api.getZr().refresh();\n },\n highlight: function (seriesModel, ecModel, api, payload) {\n this._toggleStatus('highlight', seriesModel, ecModel, api, payload);\n },\n downplay: function (seriesModel, ecModel, api, payload) {\n this._toggleStatus('downplay', seriesModel, ecModel, api, payload);\n },\n _toggleStatus: function (status, seriesModel, ecModel, api, payload) {\n var data = seriesModel.getData();\n var dataIndex = retrieve.queryDataIndex(data, payload);\n var self = this;\n\n if (dataIndex != null) {\n echarts.util.each(format.normalizeToArray(dataIndex), function (dataIdx) {\n status === 'highlight' ? this._highlight(dataIdx) : this._downplay(dataIdx);\n }, this);\n } else {\n data.each(function (dataIdx) {\n status === 'highlight' ? self._highlight(dataIdx) : self._downplay(dataIdx);\n });\n }\n },\n remove: function () {\n this.groupGL.removeAll();\n },\n dispose: function () {\n this._labelsBuilder.dispose();\n\n this.groupGL.removeAll();\n }\n});","// TODO ECharts GL must be imported whatever component,charts is imported.\nimport '../../echarts-gl';\nimport registerBarLayout from './bar3DLayout';\nimport Bar3DSeries from './Bar3DSeries';\nimport Bar3DView from './Bar3DView';\nexport function install(registers) {\n registers.registerChartView(Bar3DView);\n registers.registerSeriesModel(Bar3DSeries);\n registerBarLayout(registers);\n registers.registerProcessor(function (ecModel, api) {\n ecModel.eachSeriesByType('bar3d', function (seriesModel) {\n var data = seriesModel.getData();\n data.filterSelf(function (idx) {\n return data.hasValue(idx);\n });\n });\n });\n}","import { use } from 'echarts/lib/echarts';\nimport { install } from './bar3D/install';\nuse(install);","import * as echarts from 'echarts/lib/echarts';\nimport formatTooltip from '../common/formatTooltip';\nimport createList from '../common/createList';\nvar Line3DSeries = echarts.SeriesModel.extend({\n type: 'series.line3D',\n dependencies: ['grid3D'],\n visualStyleAccessPath: 'lineStyle',\n visualDrawType: 'stroke',\n getInitialData: function (option, ecModel) {\n return createList(this);\n },\n formatTooltip: function (dataIndex) {\n return formatTooltip(this, dataIndex);\n },\n defaultOption: {\n coordinateSystem: 'cartesian3D',\n zlevel: -10,\n // Cartesian coordinate system\n grid3DIndex: 0,\n lineStyle: {\n width: 2\n },\n animationDurationUpdate: 500\n }\n});\nexport default Line3DSeries;","import * as echarts from 'echarts/lib/echarts';\nimport graphicGL from '../../util/graphicGL';\nimport retrieve from '../../util/retrieve';\nimport Lines3DGeometry from '../../util/geometry/Lines3D';\nimport Matrix4 from 'claygl/src/math/Matrix4';\nimport Vector3 from 'claygl/src/math/Vector3';\nimport * as lineContain from 'zrender/lib/contain/line';\nimport glmatrix from 'claygl/src/dep/glmatrix';\nimport { getItemVisualColor, getItemVisualOpacity } from '../../util/visual';\nimport lines3DGLSL from '../../util/shader/lines3D.glsl.js';\nvar vec3 = glmatrix.vec3;\ngraphicGL.Shader.import(lines3DGLSL);\nexport default echarts.ChartView.extend({\n type: 'line3D',\n __ecgl__: true,\n init: function (ecModel, api) {\n this.groupGL = new graphicGL.Node();\n this._api = api;\n },\n render: function (seriesModel, ecModel, api) {\n var tmp = this._prevLine3DMesh;\n this._prevLine3DMesh = this._line3DMesh;\n this._line3DMesh = tmp;\n\n if (!this._line3DMesh) {\n this._line3DMesh = new graphicGL.Mesh({\n geometry: new Lines3DGeometry({\n useNativeLine: false,\n sortTriangles: true\n }),\n material: new graphicGL.Material({\n shader: graphicGL.createShader('ecgl.meshLines3D')\n }),\n // Render after axes\n renderOrder: 10\n });\n this._line3DMesh.geometry.pick = this._pick.bind(this);\n }\n\n this.groupGL.remove(this._prevLine3DMesh);\n this.groupGL.add(this._line3DMesh);\n var coordSys = seriesModel.coordinateSystem;\n\n if (coordSys && coordSys.viewGL) {\n coordSys.viewGL.add(this.groupGL); // TODO\n\n var methodName = coordSys.viewGL.isLinearSpace() ? 'define' : 'undefine';\n\n this._line3DMesh.material[methodName]('fragment', 'SRGB_DECODE');\n }\n\n this._doRender(seriesModel, api);\n\n this._data = seriesModel.getData();\n this._camera = coordSys.viewGL.camera;\n this.updateCamera();\n\n this._updateAnimation(seriesModel);\n },\n updateCamera: function () {\n this._updateNDCPosition();\n },\n _doRender: function (seriesModel, api) {\n var data = seriesModel.getData();\n var lineMesh = this._line3DMesh;\n lineMesh.geometry.resetOffset();\n var points = data.getLayout('points');\n var colorArr = [];\n var vertexColors = new Float32Array(points.length / 3 * 4);\n var colorOffset = 0;\n var hasTransparent = false;\n data.each(function (idx) {\n var color = getItemVisualColor(data, idx);\n var opacity = getItemVisualOpacity(data, idx);\n\n if (opacity == null) {\n opacity = 1;\n }\n\n graphicGL.parseColor(color, colorArr);\n colorArr[3] *= opacity;\n vertexColors[colorOffset++] = colorArr[0];\n vertexColors[colorOffset++] = colorArr[1];\n vertexColors[colorOffset++] = colorArr[2];\n vertexColors[colorOffset++] = colorArr[3];\n\n if (colorArr[3] < 0.99) {\n hasTransparent = true;\n }\n });\n lineMesh.geometry.setVertexCount(lineMesh.geometry.getPolylineVertexCount(points));\n lineMesh.geometry.setTriangleCount(lineMesh.geometry.getPolylineTriangleCount(points));\n lineMesh.geometry.addPolyline(points, vertexColors, retrieve.firstNotNull(seriesModel.get('lineStyle.width'), 1));\n lineMesh.geometry.dirty();\n lineMesh.geometry.updateBoundingBox();\n var material = lineMesh.material;\n material.transparent = hasTransparent;\n material.depthMask = !hasTransparent;\n var debugWireframeModel = seriesModel.getModel('debug.wireframe');\n\n if (debugWireframeModel.get('show')) {\n lineMesh.geometry.createAttribute('barycentric', 'float', 3);\n lineMesh.geometry.generateBarycentric();\n lineMesh.material.set('both', 'WIREFRAME_TRIANGLE');\n lineMesh.material.set('wireframeLineColor', graphicGL.parseColor(debugWireframeModel.get('lineStyle.color') || 'rgba(0,0,0,0.5)'));\n lineMesh.material.set('wireframeLineWidth', retrieve.firstNotNull(debugWireframeModel.get('lineStyle.width'), 1));\n } else {\n lineMesh.material.set('both', 'WIREFRAME_TRIANGLE');\n }\n\n this._points = points;\n\n this._initHandler(seriesModel, api);\n },\n _updateAnimation: function (seriesModel) {\n graphicGL.updateVertexAnimation([['prevPosition', 'position'], ['prevPositionPrev', 'positionPrev'], ['prevPositionNext', 'positionNext']], this._prevLine3DMesh, this._line3DMesh, seriesModel);\n },\n _initHandler: function (seriesModel, api) {\n var data = seriesModel.getData();\n var coordSys = seriesModel.coordinateSystem;\n var lineMesh = this._line3DMesh;\n var lastDataIndex = -1;\n lineMesh.seriesIndex = seriesModel.seriesIndex;\n lineMesh.off('mousemove');\n lineMesh.off('mouseout');\n lineMesh.on('mousemove', function (e) {\n var value = coordSys.pointToData(e.point.array);\n var dataIndex = data.indicesOfNearest('x', value[0])[0];\n\n if (dataIndex !== lastDataIndex) {\n // this._downplay(lastDataIndex);\n // this._highlight(dataIndex);\n api.dispatchAction({\n type: 'grid3DShowAxisPointer',\n value: [data.get('x', dataIndex), data.get('y', dataIndex), data.get('z', dataIndex)]\n });\n lineMesh.dataIndex = dataIndex;\n }\n\n lastDataIndex = dataIndex;\n }, this);\n lineMesh.on('mouseout', function (e) {\n // this._downplay(lastDataIndex);\n lastDataIndex = -1;\n lineMesh.dataIndex = -1;\n api.dispatchAction({\n type: 'grid3DHideAxisPointer'\n });\n }, this);\n },\n // _highlight: function (dataIndex) {\n // var data = this._data;\n // if (!data) {\n // return;\n // }\n // },\n // _downplay: function (dataIndex) {\n // var data = this._data;\n // if (!data) {\n // return;\n // }\n // },\n _updateNDCPosition: function () {\n var worldViewProjection = new Matrix4();\n var camera = this._camera;\n Matrix4.multiply(worldViewProjection, camera.projectionMatrix, camera.viewMatrix);\n var positionNDC = this._positionNDC;\n var points = this._points;\n var nPoints = points.length / 3;\n\n if (!positionNDC || positionNDC.length / 2 !== nPoints) {\n positionNDC = this._positionNDC = new Float32Array(nPoints * 2);\n }\n\n var pos = [];\n\n for (var i = 0; i < nPoints; i++) {\n var i3 = i * 3;\n var i2 = i * 2;\n pos[0] = points[i3];\n pos[1] = points[i3 + 1];\n pos[2] = points[i3 + 2];\n pos[3] = 1;\n vec3.transformMat4(pos, pos, worldViewProjection.array);\n positionNDC[i2] = pos[0] / pos[3];\n positionNDC[i2 + 1] = pos[1] / pos[3];\n }\n },\n _pick: function (x, y, renderer, camera, renderable, out) {\n var positionNDC = this._positionNDC;\n var seriesModel = this._data.hostModel;\n var lineWidth = seriesModel.get('lineStyle.width');\n var dataIndex = -1;\n var width = renderer.viewport.width;\n var height = renderer.viewport.height;\n var halfWidth = width * 0.5;\n var halfHeight = height * 0.5;\n x = (x + 1) * halfWidth;\n y = (y + 1) * halfHeight;\n\n for (var i = 1; i < positionNDC.length / 2; i++) {\n var x0 = (positionNDC[(i - 1) * 2] + 1) * halfWidth;\n var y0 = (positionNDC[(i - 1) * 2 + 1] + 1) * halfHeight;\n var x1 = (positionNDC[i * 2] + 1) * halfWidth;\n var y1 = (positionNDC[i * 2 + 1] + 1) * halfHeight;\n\n if (lineContain.containStroke(x0, y0, x1, y1, lineWidth, x, y)) {\n var dist0 = (x0 - x) * (x0 - x) + (y0 - y) * (y0 - y);\n var dist1 = (x1 - x) * (x1 - x) + (y1 - y) * (y1 - y); // Nearest point.\n\n dataIndex = dist0 < dist1 ? i - 1 : i;\n }\n }\n\n if (dataIndex >= 0) {\n var i3 = dataIndex * 3;\n var point = new Vector3(this._points[i3], this._points[i3 + 1], this._points[i3 + 2]);\n out.push({\n dataIndex: dataIndex,\n point: point,\n pointWorld: point.clone(),\n target: this._line3DMesh,\n distance: this._camera.getWorldPosition().dist(point)\n });\n }\n },\n remove: function () {\n this.groupGL.removeAll();\n },\n dispose: function () {\n this.groupGL.removeAll();\n }\n});","// TODO ECharts GL must be imported whatever component,charts is imported.\nimport '../../echarts-gl';\nimport Line3DSeries from './Line3DSeries';\nimport Line3DView from './Line3DView';\nexport function install(registers) {\n registers.registerChartView(Line3DView);\n registers.registerSeriesModel(Line3DSeries);\n registers.registerLayout(function (ecModel, api) {\n ecModel.eachSeriesByType('line3D', function (seriesModel) {\n var data = seriesModel.getData();\n var coordSys = seriesModel.coordinateSystem;\n\n if (coordSys) {\n if (coordSys.type !== 'cartesian3D') {\n if (process.env.NODE_ENV !== 'production') {\n console.error('line3D needs cartesian3D coordinateSystem');\n }\n\n return;\n }\n\n var points = new Float32Array(data.count() * 3);\n var item = [];\n var out = [];\n var coordDims = coordSys.dimensions;\n var dims = coordDims.map(function (coordDim) {\n return seriesModel.coordDimToDataDim(coordDim)[0];\n });\n\n if (coordSys) {\n data.each(dims, function (x, y, z, idx) {\n item[0] = x;\n item[1] = y;\n item[2] = z;\n coordSys.dataToPoint(item, out);\n points[idx * 3] = out[0];\n points[idx * 3 + 1] = out[1];\n points[idx * 3 + 2] = out[2];\n });\n }\n\n data.setLayout('points', points);\n }\n });\n });\n}","import { use } from 'echarts/lib/echarts';\nimport { install } from './line3D/install';\nuse(install);","import * as echarts from 'echarts/lib/echarts';\nimport formatUtil from '../../util/format';\nimport formatTooltip from '../common/formatTooltip';\nimport createList from '../common/createList';\nexport default echarts.SeriesModel.extend({\n type: 'series.scatter3D',\n dependencies: ['globe', 'grid3D', 'geo3D'],\n visualStyleAccessPath: 'itemStyle',\n hasSymbolVisual: true,\n getInitialData: function (option, ecModel) {\n return createList(this);\n },\n getFormattedLabel: function (dataIndex, status, dataType, dimIndex) {\n var text = formatUtil.getFormattedLabel(this, dataIndex, status, dataType, dimIndex);\n\n if (text == null) {\n var data = this.getData();\n var lastDim = data.dimensions[data.dimensions.length - 1];\n text = data.get(lastDim, dataIndex);\n }\n\n return text;\n },\n formatTooltip: function (dataIndex) {\n return formatTooltip(this, dataIndex);\n },\n defaultOption: {\n coordinateSystem: 'cartesian3D',\n zlevel: -10,\n progressive: 1e5,\n progressiveThreshold: 1e5,\n // Cartesian coordinate system\n grid3DIndex: 0,\n globeIndex: 0,\n symbol: 'circle',\n symbolSize: 10,\n // Support source-over, lighter\n blendMode: 'source-over',\n label: {\n show: false,\n position: 'right',\n // Screen space distance\n distance: 5,\n textStyle: {\n fontSize: 14,\n color: '#000',\n backgroundColor: 'rgba(255,255,255,0.7)',\n padding: 3,\n borderRadius: 3\n }\n },\n itemStyle: {\n opacity: 0.8\n },\n emphasis: {\n label: {\n show: true\n }\n },\n animationDurationUpdate: 500\n }\n});","import * as echarts from 'echarts/lib/echarts';\n\nfunction makeSprite(size, canvas, draw) {\n // http://simonsarris.com/blog/346-how-you-clear-your-canvas-matters\n // http://jsperf.com/canvasclear\n // Set width and height is fast\n // And use the exist canvas if possible\n // http://jsperf.com/create-canvas-vs-set-width-height/2\n var canvas = canvas || document.createElement('canvas');\n canvas.width = size;\n canvas.height = size;\n var ctx = canvas.getContext('2d');\n draw && draw(ctx);\n return canvas;\n}\n\nfunction makePath(symbol, symbolSize, style, marginBias) {\n if (!echarts.util.isArray(symbolSize)) {\n symbolSize = [symbolSize, symbolSize];\n }\n\n var margin = spriteUtil.getMarginByStyle(style, marginBias);\n var width = symbolSize[0] + margin.left + margin.right;\n var height = symbolSize[1] + margin.top + margin.bottom;\n var path = echarts.helper.createSymbol(symbol, 0, 0, symbolSize[0], symbolSize[1]);\n var size = Math.max(width, height);\n path.x = margin.left;\n path.y = margin.top;\n\n if (width > height) {\n path.y += (size - height) / 2;\n } else {\n path.x += (size - width) / 2;\n }\n\n var rect = path.getBoundingRect();\n path.x -= rect.x;\n path.y -= rect.y;\n path.setStyle(style);\n path.update();\n path.__size = size;\n return path;\n} // http://www.valvesoftware.com/publications/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf\n\n\nfunction generateSDF(ctx, sourceImageData, range) {\n var sourceWidth = sourceImageData.width;\n var sourceHeight = sourceImageData.height;\n var width = ctx.canvas.width;\n var height = ctx.canvas.height;\n var scaleX = sourceWidth / width;\n var scaleY = sourceHeight / height;\n\n function sign(r) {\n return r < 128 ? 1 : -1;\n }\n\n function searchMinDistance(x, y) {\n var minDistSqr = Infinity;\n x = Math.floor(x * scaleX);\n y = Math.floor(y * scaleY);\n var i = y * sourceWidth + x;\n var r = sourceImageData.data[i * 4];\n var a = sign(r); // Search for min distance\n\n for (var y2 = Math.max(y - range, 0); y2 < Math.min(y + range, sourceHeight); y2++) {\n for (var x2 = Math.max(x - range, 0); x2 < Math.min(x + range, sourceWidth); x2++) {\n var i = y2 * sourceWidth + x2;\n var r2 = sourceImageData.data[i * 4];\n var b = sign(r2);\n var dx = x2 - x;\n var dy = y2 - y;\n\n if (a !== b) {\n var distSqr = dx * dx + dy * dy;\n\n if (distSqr < minDistSqr) {\n minDistSqr = distSqr;\n }\n }\n }\n }\n\n return a * Math.sqrt(minDistSqr);\n }\n\n var sdfImageData = ctx.createImageData(width, height);\n\n for (var y = 0; y < height; y++) {\n for (var x = 0; x < width; x++) {\n var dist = searchMinDistance(x, y);\n var normalized = dist / range * 0.5 + 0.5;\n var i = (y * width + x) * 4;\n sdfImageData.data[i++] = (1.0 - normalized) * 255;\n sdfImageData.data[i++] = (1.0 - normalized) * 255;\n sdfImageData.data[i++] = (1.0 - normalized) * 255;\n sdfImageData.data[i++] = 255;\n }\n }\n\n return sdfImageData;\n}\n\nvar spriteUtil = {\n getMarginByStyle: function (style) {\n var minMargin = style.minMargin || 0;\n var lineWidth = 0;\n\n if (style.stroke && style.stroke !== 'none') {\n lineWidth = style.lineWidth == null ? 1 : style.lineWidth;\n }\n\n var shadowBlurSize = style.shadowBlur || 0;\n var shadowOffsetX = style.shadowOffsetX || 0;\n var shadowOffsetY = style.shadowOffsetY || 0;\n var margin = {};\n margin.left = Math.max(lineWidth / 2, -shadowOffsetX + shadowBlurSize, minMargin);\n margin.right = Math.max(lineWidth / 2, shadowOffsetX + shadowBlurSize, minMargin);\n margin.top = Math.max(lineWidth / 2, -shadowOffsetY + shadowBlurSize, minMargin);\n margin.bottom = Math.max(lineWidth / 2, shadowOffsetY + shadowBlurSize, minMargin);\n return margin;\n },\n // TODO Not consider shadowOffsetX, shadowOffsetY.\n\n /**\n * @param {string} symbol\n * @param {number | Array.} symbolSize\n * @param {Object} style\n */\n createSymbolSprite: function (symbol, symbolSize, style, canvas) {\n var path = makePath(symbol, symbolSize, style);\n var margin = spriteUtil.getMarginByStyle(style);\n return {\n image: makeSprite(path.__size, canvas, function (ctx) {\n echarts.innerDrawElementOnCanvas(ctx, path);\n }),\n margin: margin\n };\n },\n createSDFFromCanvas: function (canvas, size, range, outCanvas) {\n // TODO Create a low resolution SDF from high resolution image.\n return makeSprite(size, outCanvas, function (outCtx) {\n var ctx = canvas.getContext('2d');\n var imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);\n outCtx.putImageData(generateSDF(outCtx, imgData, range), 0, 0);\n });\n },\n createSimpleSprite: function (size, canvas) {\n return makeSprite(size, canvas, function (ctx) {\n var halfSize = size / 2;\n ctx.beginPath();\n ctx.arc(halfSize, halfSize, 60, 0, Math.PI * 2, false);\n ctx.closePath();\n var gradient = ctx.createRadialGradient(halfSize, halfSize, 0, halfSize, halfSize, halfSize);\n gradient.addColorStop(0, 'rgba(255, 255, 255, 1)');\n gradient.addColorStop(0.5, 'rgba(255, 255, 255, 0.5)');\n gradient.addColorStop(1, 'rgba(255, 255, 255, 0)');\n ctx.fillStyle = gradient;\n ctx.fill();\n });\n }\n};\nexport default spriteUtil;","import ProgressiveQuickSort from '../ProgressiveQuickSort';\nimport glmatrix from 'claygl/src/dep/glmatrix';\nvar vec3 = glmatrix.vec3;\nexport default {\n needsSortVertices: function () {\n return this.sortVertices;\n },\n needsSortVerticesProgressively: function () {\n return this.needsSortVertices() && this.vertexCount >= 2e4;\n },\n doSortVertices: function (cameraPos, frame) {\n var indices = this.indices;\n var p = vec3.create();\n\n if (!indices) {\n indices = this.indices = this.vertexCount > 0xffff ? new Uint32Array(this.vertexCount) : new Uint16Array(this.vertexCount);\n\n for (var i = 0; i < indices.length; i++) {\n indices[i] = i;\n }\n } // Do progressive quick sort.\n\n\n if (frame === 0) {\n var posAttr = this.attributes.position;\n var cameraPos = cameraPos.array;\n var noneCount = 0;\n\n if (!this._zList || this._zList.length !== this.vertexCount) {\n this._zList = new Float32Array(this.vertexCount);\n }\n\n var firstZ;\n\n for (var i = 0; i < this.vertexCount; i++) {\n posAttr.get(i, p); // Camera position is in object space\n\n var z = vec3.sqrDist(p, cameraPos);\n\n if (isNaN(z)) {\n // Put far away, NaN value may cause sort slow\n z = 1e7;\n noneCount++;\n }\n\n if (i === 0) {\n firstZ = z;\n z = 0;\n } else {\n // Only store the difference to avoid the precision issue.\n z = z - firstZ;\n }\n\n this._zList[i] = z;\n }\n\n this._noneCount = noneCount;\n }\n\n if (this.vertexCount < 2e4) {\n // Use simple native sort for simple geometries.\n if (frame === 0) {\n this._simpleSort(this._noneCount / this.vertexCount > 0.05);\n }\n } else {\n for (var i = 0; i < 3; i++) {\n this._progressiveQuickSort(frame * 3 + i);\n }\n }\n\n this.dirtyIndices();\n },\n _simpleSort: function (useNativeQuickSort) {\n var zList = this._zList;\n var indices = this.indices;\n\n function compare(a, b) {\n // Sort from far to near. which is descending order\n return zList[b] - zList[a];\n } // When too much value are equal, using native quick sort with three partition..\n // or the simple quick sort will be nearly O(n*n)\n // http://stackoverflow.com/questions/5126586/quicksort-complexity-when-all-the-elements-are-same\n // Otherwise simple quicksort is more effecient than v8 native quick sort when data all different.\n\n\n if (useNativeQuickSort) {\n Array.prototype.sort.call(indices, compare);\n } else {\n ProgressiveQuickSort.sort(indices, compare, 0, indices.length - 1);\n }\n },\n _progressiveQuickSort: function (frame) {\n var zList = this._zList;\n var indices = this.indices;\n this._quickSort = this._quickSort || new ProgressiveQuickSort();\n\n this._quickSort.step(indices, function (a, b) {\n return zList[b] - zList[a];\n }, frame);\n }\n};","export default \"@export ecgl.sdfSprite.vertex\\n\\nuniform mat4 worldViewProjection : WORLDVIEWPROJECTION;\\nuniform float elapsedTime : 0;\\n\\nattribute vec3 position : POSITION;\\n\\n#ifdef VERTEX_SIZE\\nattribute float size;\\n#else\\nuniform float u_Size;\\n#endif\\n\\n#ifdef VERTEX_COLOR\\nattribute vec4 a_FillColor: COLOR;\\nvarying vec4 v_Color;\\n#endif\\n\\n#ifdef VERTEX_ANIMATION\\nattribute vec3 prevPosition;\\nattribute float prevSize;\\nuniform float percent : 1.0;\\n#endif\\n\\n\\n#ifdef POSITIONTEXTURE_ENABLED\\nuniform sampler2D positionTexture;\\n#endif\\n\\nvarying float v_Size;\\n\\nvoid main()\\n{\\n\\n#ifdef POSITIONTEXTURE_ENABLED\\n gl_Position = worldViewProjection * vec4(texture2D(positionTexture, position.xy).xy, -10.0, 1.0);\\n#else\\n\\n #ifdef VERTEX_ANIMATION\\n vec3 pos = mix(prevPosition, position, percent);\\n #else\\n vec3 pos = position;\\n #endif\\n gl_Position = worldViewProjection * vec4(pos, 1.0);\\n#endif\\n\\n#ifdef VERTEX_SIZE\\n#ifdef VERTEX_ANIMATION\\n v_Size = mix(prevSize, size, percent);\\n#else\\n v_Size = size;\\n#endif\\n#else\\n v_Size = u_Size;\\n#endif\\n\\n#ifdef VERTEX_COLOR\\n v_Color = a_FillColor;\\n #endif\\n\\n gl_PointSize = v_Size;\\n}\\n\\n@end\\n\\n@export ecgl.sdfSprite.fragment\\n\\nuniform vec4 color: [1, 1, 1, 1];\\nuniform vec4 strokeColor: [1, 1, 1, 1];\\nuniform float smoothing: 0.07;\\n\\nuniform float lineWidth: 0.0;\\n\\n#ifdef VERTEX_COLOR\\nvarying vec4 v_Color;\\n#endif\\n\\nvarying float v_Size;\\n\\nuniform sampler2D sprite;\\n\\n@import clay.util.srgb\\n\\nvoid main()\\n{\\n gl_FragColor = color;\\n\\n vec4 _strokeColor = strokeColor;\\n\\n#ifdef VERTEX_COLOR\\n gl_FragColor *= v_Color;\\n #endif\\n\\n#ifdef SPRITE_ENABLED\\n float d = texture2D(sprite, gl_PointCoord).r;\\n gl_FragColor.a *= smoothstep(0.5 - smoothing, 0.5 + smoothing, d);\\n\\n if (lineWidth > 0.0) {\\n float sLineWidth = lineWidth / 2.0;\\n\\n float outlineMaxValue0 = 0.5 + sLineWidth;\\n float outlineMaxValue1 = 0.5 + sLineWidth + smoothing;\\n float outlineMinValue0 = 0.5 - sLineWidth - smoothing;\\n float outlineMinValue1 = 0.5 - sLineWidth;\\n\\n if (d <= outlineMaxValue1 && d >= outlineMinValue0) {\\n float a = _strokeColor.a;\\n if (d <= outlineMinValue1) {\\n a = a * smoothstep(outlineMinValue0, outlineMinValue1, d);\\n }\\n else {\\n a = a * smoothstep(outlineMaxValue1, outlineMaxValue0, d);\\n }\\n gl_FragColor.rgb = mix(gl_FragColor.rgb * gl_FragColor.a, _strokeColor.rgb, a);\\n gl_FragColor.a = gl_FragColor.a * (1.0 - a) + a;\\n }\\n }\\n#endif\\n\\n#ifdef SRGB_DECODE\\n gl_FragColor = sRGBToLinear(gl_FragColor);\\n#endif\\n}\\n@end\";","import graphicGL from '../../util/graphicGL';\nimport verticesSortMixin from '../../util/geometry/verticesSortMixin';\nimport * as echarts from 'echarts/lib/echarts';\nimport glmatrix from 'claygl/src/dep/glmatrix';\nvar vec4 = glmatrix.vec4;\nimport sdfSpriteGLSL from './sdfSprite.glsl.js';\ngraphicGL.Shader.import(sdfSpriteGLSL);\nvar PointsMesh = graphicGL.Mesh.extend(function () {\n var geometry = new graphicGL.Geometry({\n dynamic: true,\n attributes: {\n color: new graphicGL.Geometry.Attribute('color', 'float', 4, 'COLOR'),\n position: new graphicGL.Geometry.Attribute('position', 'float', 3, 'POSITION'),\n size: new graphicGL.Geometry.Attribute('size', 'float', 1),\n prevPosition: new graphicGL.Geometry.Attribute('prevPosition', 'float', 3),\n prevSize: new graphicGL.Geometry.Attribute('prevSize', 'float', 1)\n }\n });\n Object.assign(geometry, verticesSortMixin);\n var material = new graphicGL.Material({\n shader: graphicGL.createShader('ecgl.sdfSprite'),\n transparent: true,\n depthMask: false\n });\n material.enableTexture('sprite');\n material.define('both', 'VERTEX_COLOR');\n material.define('both', 'VERTEX_SIZE');\n var sdfTexture = new graphicGL.Texture2D({\n image: document.createElement('canvas'),\n flipY: false\n });\n material.set('sprite', sdfTexture); // Custom pick methods.\n\n geometry.pick = this._pick.bind(this);\n return {\n geometry: geometry,\n material: material,\n mode: graphicGL.Mesh.POINTS,\n sizeScale: 1\n };\n}, {\n _pick: function (x, y, renderer, camera, renderable, out) {\n var positionNDC = this._positionNDC;\n\n if (!positionNDC) {\n return;\n }\n\n var viewport = renderer.viewport;\n var ndcScaleX = 2 / viewport.width;\n var ndcScaleY = 2 / viewport.height; // From near to far. indices have been sorted.\n\n for (var i = this.geometry.vertexCount - 1; i >= 0; i--) {\n var idx;\n\n if (!this.geometry.indices) {\n idx = i;\n } else {\n idx = this.geometry.indices[i];\n }\n\n var cx = positionNDC[idx * 2];\n var cy = positionNDC[idx * 2 + 1];\n var size = this.geometry.attributes.size.get(idx) / this.sizeScale;\n var halfSize = size / 2;\n\n if (x > cx - halfSize * ndcScaleX && x < cx + halfSize * ndcScaleX && y > cy - halfSize * ndcScaleY && y < cy + halfSize * ndcScaleY) {\n var point = new graphicGL.Vector3();\n var pointWorld = new graphicGL.Vector3();\n this.geometry.attributes.position.get(idx, point.array);\n graphicGL.Vector3.transformMat4(pointWorld, point, this.worldTransform);\n out.push({\n vertexIndex: idx,\n point: point,\n pointWorld: pointWorld,\n target: this,\n distance: pointWorld.distance(camera.getWorldPosition())\n });\n }\n }\n },\n updateNDCPosition: function (worldViewProjection, is2D, api) {\n var positionNDC = this._positionNDC;\n var geometry = this.geometry;\n\n if (!positionNDC || positionNDC.length / 2 !== geometry.vertexCount) {\n positionNDC = this._positionNDC = new Float32Array(geometry.vertexCount * 2);\n }\n\n var pos = vec4.create();\n\n for (var i = 0; i < geometry.vertexCount; i++) {\n geometry.attributes.position.get(i, pos);\n pos[3] = 1;\n vec4.transformMat4(pos, pos, worldViewProjection.array);\n vec4.scale(pos, pos, 1 / pos[3]);\n positionNDC[i * 2] = pos[0];\n positionNDC[i * 2 + 1] = pos[1];\n }\n }\n});\nexport default PointsMesh;","import * as echarts from 'echarts/lib/echarts';\nimport graphicGL from '../../util/graphicGL';\nimport spriteUtil from '../../util/sprite';\nimport PointsMesh from './PointsMesh';\nimport LabelsBuilder from '../../component/common/LabelsBuilder';\nimport Matrix4 from 'claygl/src/math/Matrix4';\nimport retrieve from '../../util/retrieve';\nimport { getItemVisualColor, getItemVisualOpacity } from '../../util/visual';\nimport { getVisualColor, getVisualOpacity } from '../../util/visual';\nvar SDF_RANGE = 20;\nvar Z_2D = -10;\n\nfunction isSymbolSizeSame(a, b) {\n return a && b && a[0] === b[0] && a[1] === b[1];\n} // TODO gl_PointSize has max value.\n\n\nfunction PointsBuilder(is2D, api) {\n this.rootNode = new graphicGL.Node();\n /**\n * @type {boolean}\n */\n\n this.is2D = is2D;\n this._labelsBuilder = new LabelsBuilder(256, 256, api); // Give a large render order.\n\n this._labelsBuilder.getMesh().renderOrder = 100;\n this.rootNode.add(this._labelsBuilder.getMesh());\n this._api = api;\n this._spriteImageCanvas = document.createElement('canvas');\n this._startDataIndex = 0;\n this._endDataIndex = 0;\n this._sizeScale = 1;\n}\n\nPointsBuilder.prototype = {\n constructor: PointsBuilder,\n\n /**\n * If highlight on over\n */\n highlightOnMouseover: true,\n update: function (seriesModel, ecModel, api, start, end) {\n // Swap barMesh\n var tmp = this._prevMesh;\n this._prevMesh = this._mesh;\n this._mesh = tmp;\n var data = seriesModel.getData();\n\n if (start == null) {\n start = 0;\n }\n\n if (end == null) {\n end = data.count();\n }\n\n this._startDataIndex = start;\n this._endDataIndex = end - 1;\n\n if (!this._mesh) {\n var material = this._prevMesh && this._prevMesh.material;\n this._mesh = new PointsMesh({\n // Render after axes\n renderOrder: 10,\n // FIXME\n frustumCulling: false\n });\n\n if (material) {\n this._mesh.material = material;\n }\n }\n\n var material = this._mesh.material;\n var geometry = this._mesh.geometry;\n var attributes = geometry.attributes;\n this.rootNode.remove(this._prevMesh);\n this.rootNode.add(this._mesh);\n\n this._setPositionTextureToMesh(this._mesh, this._positionTexture);\n\n var symbolInfo = this._getSymbolInfo(seriesModel, start, end);\n\n var dpr = api.getDevicePixelRatio(); // TODO image symbol\n\n var itemStyle = seriesModel.getModel('itemStyle').getItemStyle();\n var largeMode = seriesModel.get('large');\n var pointSizeScale = 1;\n\n if (symbolInfo.maxSize > 2) {\n pointSizeScale = this._updateSymbolSprite(seriesModel, itemStyle, symbolInfo, dpr);\n material.enableTexture('sprite');\n } else {\n material.disableTexture('sprite');\n }\n\n attributes.position.init(end - start);\n var rgbaArr = [];\n\n if (largeMode) {\n material.undefine('VERTEX_SIZE');\n material.undefine('VERTEX_COLOR');\n var color = getVisualColor(data);\n var opacity = getVisualOpacity(data);\n graphicGL.parseColor(color, rgbaArr);\n rgbaArr[3] *= opacity;\n material.set({\n color: rgbaArr,\n 'u_Size': symbolInfo.maxSize * this._sizeScale\n });\n } else {\n material.set({\n color: [1, 1, 1, 1]\n });\n material.define('VERTEX_SIZE');\n material.define('VERTEX_COLOR');\n attributes.size.init(end - start);\n attributes.color.init(end - start);\n this._originalOpacity = new Float32Array(end - start);\n }\n\n var points = data.getLayout('points');\n var positionArr = attributes.position.value;\n var hasTransparentPoint = false;\n\n for (var i = 0; i < end - start; i++) {\n var i3 = i * 3;\n var i2 = i * 2;\n\n if (this.is2D) {\n positionArr[i3] = points[i2];\n positionArr[i3 + 1] = points[i2 + 1];\n positionArr[i3 + 2] = Z_2D;\n } else {\n positionArr[i3] = points[i3];\n positionArr[i3 + 1] = points[i3 + 1];\n positionArr[i3 + 2] = points[i3 + 2];\n }\n\n if (!largeMode) {\n var color = getItemVisualColor(data, i);\n var opacity = getItemVisualOpacity(data, i);\n graphicGL.parseColor(color, rgbaArr);\n rgbaArr[3] *= opacity;\n attributes.color.set(i, rgbaArr);\n\n if (rgbaArr[3] < 0.99) {\n hasTransparentPoint = true;\n }\n\n var symbolSize = data.getItemVisual(i, 'symbolSize');\n symbolSize = symbolSize instanceof Array ? Math.max(symbolSize[0], symbolSize[1]) : symbolSize; // NaN pointSize may have strange result.\n\n if (isNaN(symbolSize)) {\n symbolSize = 0;\n } // Scale point size because canvas has margin.\n\n\n attributes.size.value[i] = symbolSize * pointSizeScale * this._sizeScale; // Save the original opacity for recover from fadeIn.\n\n this._originalOpacity[i] = rgbaArr[3];\n }\n }\n\n this._mesh.sizeScale = pointSizeScale;\n geometry.updateBoundingBox();\n geometry.dirty(); // Update material.\n\n this._updateMaterial(seriesModel, itemStyle);\n\n var coordSys = seriesModel.coordinateSystem;\n\n if (coordSys && coordSys.viewGL) {\n var methodName = coordSys.viewGL.isLinearSpace() ? 'define' : 'undefine';\n material[methodName]('fragment', 'SRGB_DECODE');\n }\n\n if (!largeMode) {\n this._updateLabelBuilder(seriesModel, start, end);\n }\n\n this._updateHandler(seriesModel, ecModel, api);\n\n this._updateAnimation(seriesModel);\n\n this._api = api;\n },\n getPointsMesh: function () {\n return this._mesh;\n },\n updateLabels: function (highlightDataIndices) {\n this._labelsBuilder.updateLabels(highlightDataIndices);\n },\n hideLabels: function () {\n this.rootNode.remove(this._labelsBuilder.getMesh());\n },\n showLabels: function () {\n this.rootNode.add(this._labelsBuilder.getMesh());\n },\n dispose: function () {\n this._labelsBuilder.dispose();\n },\n _updateSymbolSprite: function (seriesModel, itemStyle, symbolInfo, dpr) {\n symbolInfo.maxSize = Math.min(symbolInfo.maxSize * 2, 200);\n var symbolSize = [];\n\n if (symbolInfo.aspect > 1) {\n symbolSize[0] = symbolInfo.maxSize;\n symbolSize[1] = symbolInfo.maxSize / symbolInfo.aspect;\n } else {\n symbolSize[1] = symbolInfo.maxSize;\n symbolSize[0] = symbolInfo.maxSize * symbolInfo.aspect;\n } // In case invalid data.\n\n\n symbolSize[0] = symbolSize[0] || 1;\n symbolSize[1] = symbolSize[1] || 1;\n\n if (this._symbolType !== symbolInfo.type || !isSymbolSizeSame(this._symbolSize, symbolSize) || this._lineWidth !== itemStyle.lineWidth) {\n spriteUtil.createSymbolSprite(symbolInfo.type, symbolSize, {\n fill: '#fff',\n lineWidth: itemStyle.lineWidth,\n stroke: 'transparent',\n shadowColor: 'transparent',\n minMargin: Math.min(symbolSize[0] / 2, 10)\n }, this._spriteImageCanvas);\n spriteUtil.createSDFFromCanvas(this._spriteImageCanvas, Math.min(this._spriteImageCanvas.width, 32), SDF_RANGE, this._mesh.material.get('sprite').image);\n this._symbolType = symbolInfo.type;\n this._symbolSize = symbolSize;\n this._lineWidth = itemStyle.lineWidth;\n }\n\n return this._spriteImageCanvas.width / symbolInfo.maxSize * dpr;\n },\n _updateMaterial: function (seriesModel, itemStyle) {\n var blendFunc = seriesModel.get('blendMode') === 'lighter' ? graphicGL.additiveBlend : null;\n var material = this._mesh.material;\n material.blend = blendFunc;\n material.set('lineWidth', itemStyle.lineWidth / SDF_RANGE);\n var strokeColor = graphicGL.parseColor(itemStyle.stroke);\n material.set('strokeColor', strokeColor); // Because of symbol texture, we always needs it be transparent.\n\n material.transparent = true;\n material.depthMask = false;\n material.depthTest = !this.is2D;\n material.sortVertices = !this.is2D;\n },\n _updateLabelBuilder: function (seriesModel, start, end) {\n var data = seriesModel.getData();\n var geometry = this._mesh.geometry;\n var positionArr = geometry.attributes.position.value;\n var start = this._startDataIndex;\n var pointSizeScale = this._mesh.sizeScale;\n\n this._labelsBuilder.updateData(data, start, end);\n\n this._labelsBuilder.getLabelPosition = function (dataIndex, positionDesc, distance) {\n var idx3 = (dataIndex - start) * 3;\n return [positionArr[idx3], positionArr[idx3 + 1], positionArr[idx3 + 2]];\n };\n\n this._labelsBuilder.getLabelDistance = function (dataIndex, positionDesc, distance) {\n var size = geometry.attributes.size.get(dataIndex - start) / pointSizeScale;\n return size / 2 + distance;\n };\n\n this._labelsBuilder.updateLabels();\n },\n _updateAnimation: function (seriesModel) {\n graphicGL.updateVertexAnimation([['prevPosition', 'position'], ['prevSize', 'size']], this._prevMesh, this._mesh, seriesModel);\n },\n _updateHandler: function (seriesModel, ecModel, api) {\n var data = seriesModel.getData();\n var pointsMesh = this._mesh;\n var self = this;\n var lastDataIndex = -1;\n var isCartesian3D = seriesModel.coordinateSystem && seriesModel.coordinateSystem.type === 'cartesian3D';\n var grid3DModel;\n\n if (isCartesian3D) {\n grid3DModel = seriesModel.coordinateSystem.model;\n }\n\n pointsMesh.seriesIndex = seriesModel.seriesIndex;\n pointsMesh.off('mousemove');\n pointsMesh.off('mouseout');\n pointsMesh.on('mousemove', function (e) {\n var dataIndex = e.vertexIndex + self._startDataIndex;\n\n if (dataIndex !== lastDataIndex) {\n if (this.highlightOnMouseover) {\n this.downplay(data, lastDataIndex);\n this.highlight(data, dataIndex);\n\n this._labelsBuilder.updateLabels([dataIndex]);\n }\n\n if (isCartesian3D) {\n api.dispatchAction({\n type: 'grid3DShowAxisPointer',\n value: [data.get(seriesModel.coordDimToDataDim('x')[0], dataIndex), data.get(seriesModel.coordDimToDataDim('y')[0], dataIndex), data.get(seriesModel.coordDimToDataDim('z')[0], dataIndex)],\n grid3DIndex: grid3DModel.componentIndex\n });\n }\n }\n\n pointsMesh.dataIndex = dataIndex;\n lastDataIndex = dataIndex;\n }, this);\n pointsMesh.on('mouseout', function (e) {\n var dataIndex = e.vertexIndex + self._startDataIndex;\n\n if (this.highlightOnMouseover) {\n this.downplay(data, dataIndex);\n\n this._labelsBuilder.updateLabels();\n }\n\n lastDataIndex = -1;\n pointsMesh.dataIndex = -1;\n\n if (isCartesian3D) {\n api.dispatchAction({\n type: 'grid3DHideAxisPointer',\n grid3DIndex: grid3DModel.componentIndex\n });\n }\n }, this);\n },\n updateLayout: function (seriesModel, ecModel, api) {\n var data = seriesModel.getData();\n\n if (!this._mesh) {\n return;\n }\n\n var positionArr = this._mesh.geometry.attributes.position.value;\n var points = data.getLayout('points');\n\n if (this.is2D) {\n for (var i = 0; i < points.length / 2; i++) {\n var i3 = i * 3;\n var i2 = i * 2;\n positionArr[i3] = points[i2];\n positionArr[i3 + 1] = points[i2 + 1];\n positionArr[i3 + 2] = Z_2D;\n }\n } else {\n for (var i = 0; i < points.length; i++) {\n positionArr[i] = points[i];\n }\n }\n\n this._mesh.geometry.dirty();\n\n api.getZr().refresh();\n },\n updateView: function (camera) {\n if (!this._mesh) {\n return;\n }\n\n var worldViewProjection = new Matrix4();\n Matrix4.mul(worldViewProjection, camera.viewMatrix, this._mesh.worldTransform);\n Matrix4.mul(worldViewProjection, camera.projectionMatrix, worldViewProjection);\n\n this._mesh.updateNDCPosition(worldViewProjection, this.is2D, this._api);\n },\n highlight: function (data, dataIndex) {\n if (dataIndex > this._endDataIndex || dataIndex < this._startDataIndex) {\n return;\n }\n\n var itemModel = data.getItemModel(dataIndex);\n var emphasisItemStyleModel = itemModel.getModel('emphasis.itemStyle');\n var emphasisColor = emphasisItemStyleModel.get('color');\n var emphasisOpacity = emphasisItemStyleModel.get('opacity');\n\n if (emphasisColor == null) {\n var color = getItemVisualColor(data, dataIndex);\n emphasisColor = echarts.color.lift(color, -0.4);\n }\n\n if (emphasisOpacity == null) {\n emphasisOpacity = getItemVisualOpacity(data, dataIndex);\n }\n\n var colorArr = graphicGL.parseColor(emphasisColor);\n colorArr[3] *= emphasisOpacity;\n\n this._mesh.geometry.attributes.color.set(dataIndex - this._startDataIndex, colorArr);\n\n this._mesh.geometry.dirtyAttribute('color');\n\n this._api.getZr().refresh();\n },\n downplay: function (data, dataIndex) {\n if (dataIndex > this._endDataIndex || dataIndex < this._startDataIndex) {\n return;\n }\n\n var color = getItemVisualColor(data, dataIndex);\n var opacity = getItemVisualOpacity(data, dataIndex);\n var colorArr = graphicGL.parseColor(color);\n colorArr[3] *= opacity;\n\n this._mesh.geometry.attributes.color.set(dataIndex - this._startDataIndex, colorArr);\n\n this._mesh.geometry.dirtyAttribute('color');\n\n this._api.getZr().refresh();\n },\n fadeOutAll: function (fadeOutPercent) {\n if (this._originalOpacity) {\n var geo = this._mesh.geometry;\n\n for (var i = 0; i < geo.vertexCount; i++) {\n var fadeOutOpacity = this._originalOpacity[i] * fadeOutPercent;\n geo.attributes.color.value[i * 4 + 3] = fadeOutOpacity;\n }\n\n geo.dirtyAttribute('color');\n\n this._api.getZr().refresh();\n }\n },\n fadeInAll: function () {\n this.fadeOutAll(1);\n },\n setPositionTexture: function (texture) {\n if (this._mesh) {\n this._setPositionTextureToMesh(this._mesh, texture);\n }\n\n this._positionTexture = texture;\n },\n removePositionTexture: function () {\n this._positionTexture = null;\n\n if (this._mesh) {\n this._setPositionTextureToMesh(this._mesh, null);\n }\n },\n setSizeScale: function (sizeScale) {\n if (sizeScale !== this._sizeScale) {\n if (this._mesh) {\n var originalSize = this._mesh.material.get('u_Size');\n\n this._mesh.material.set('u_Size', originalSize / this._sizeScale * sizeScale);\n\n var attributes = this._mesh.geometry.attributes;\n\n if (attributes.size.value) {\n for (var i = 0; i < attributes.size.value.length; i++) {\n attributes.size.value[i] = attributes.size.value[i] / this._sizeScale * sizeScale;\n }\n }\n }\n\n this._sizeScale = sizeScale;\n }\n },\n _setPositionTextureToMesh: function (mesh, texture) {\n if (texture) {\n mesh.material.set('positionTexture', texture);\n }\n\n mesh.material[texture ? 'enableTexture' : 'disableTexture']('positionTexture');\n },\n _getSymbolInfo: function (seriesModel, start, end) {\n if (seriesModel.get('large')) {\n var symbolSize = retrieve.firstNotNull(seriesModel.get('symbolSize'), 1);\n var maxSymbolSize;\n var symbolAspect;\n\n if (symbolSize instanceof Array) {\n maxSymbolSize = Math.max(symbolSize[0], symbolSize[1]);\n symbolAspect = symbolSize[0] / symbolSize[1];\n } else {\n maxSymbolSize = symbolSize;\n symbolAspect = 1;\n }\n\n return {\n maxSize: symbolSize,\n type: seriesModel.get('symbol'),\n aspect: symbolAspect\n };\n }\n\n var data = seriesModel.getData();\n var symbolAspect;\n var differentSymbolAspect = false;\n var symbolType = data.getItemVisual(0, 'symbol') || 'circle';\n var differentSymbolType = false;\n var maxSymbolSize = 0;\n\n for (var idx = start; idx < end; idx++) {\n var symbolSize = data.getItemVisual(idx, 'symbolSize');\n var currentSymbolType = data.getItemVisual(idx, 'symbol');\n var currentSymbolAspect;\n\n if (!(symbolSize instanceof Array)) {\n // Ignore NaN value.\n if (isNaN(symbolSize)) {\n continue;\n }\n\n currentSymbolAspect = 1;\n maxSymbolSize = Math.max(symbolSize, maxSymbolSize);\n } else {\n currentSymbolAspect = symbolSize[0] / symbolSize[1];\n maxSymbolSize = Math.max(Math.max(symbolSize[0], symbolSize[1]), maxSymbolSize);\n }\n\n if (process.env.NODE_ENV !== 'production') {\n if (symbolAspect != null && Math.abs(currentSymbolAspect - symbolAspect) > 0.05) {\n differentSymbolAspect = true;\n }\n\n if (currentSymbolType !== symbolType) {\n differentSymbolType = true;\n }\n }\n\n symbolType = currentSymbolType;\n symbolAspect = currentSymbolAspect;\n }\n\n if (process.env.NODE_ENV !== 'production') {\n if (differentSymbolAspect) {\n console.warn('Different symbol width / height ratio will be ignored.');\n }\n\n if (differentSymbolType) {\n console.warn('Different symbol type will be ignored.');\n }\n }\n\n return {\n maxSize: maxSymbolSize,\n type: symbolType,\n aspect: symbolAspect\n };\n }\n};\nexport default PointsBuilder;","import * as echarts from 'echarts/lib/echarts';\nimport graphicGL from '../../util/graphicGL';\nimport retrieve from '../../util/retrieve';\nimport format from '../../util/format';\nimport PointsBuilder from '../common/PointsBuilder';\nexport default echarts.ChartView.extend({\n type: 'scatter3D',\n hasSymbolVisual: true,\n __ecgl__: true,\n init: function (ecModel, api) {\n this.groupGL = new graphicGL.Node();\n this._pointsBuilderList = [];\n this._currentStep = 0;\n },\n render: function (seriesModel, ecModel, api) {\n this.groupGL.removeAll();\n\n if (!seriesModel.getData().count()) {\n return;\n }\n\n var coordSys = seriesModel.coordinateSystem;\n\n if (coordSys && coordSys.viewGL) {\n coordSys.viewGL.add(this.groupGL);\n this._camera = coordSys.viewGL.camera;\n var pointsBuilder = this._pointsBuilderList[0];\n\n if (!pointsBuilder) {\n pointsBuilder = this._pointsBuilderList[0] = new PointsBuilder(false, api);\n }\n\n this._pointsBuilderList.length = 1;\n this.groupGL.add(pointsBuilder.rootNode);\n pointsBuilder.update(seriesModel, ecModel, api);\n pointsBuilder.updateView(coordSys.viewGL.camera);\n } else {\n if (process.env.NODE_ENV !== 'production') {\n throw new Error('Invalid coordinate system');\n }\n }\n },\n incrementalPrepareRender: function (seriesModel, ecModel, api) {\n var coordSys = seriesModel.coordinateSystem;\n\n if (coordSys && coordSys.viewGL) {\n coordSys.viewGL.add(this.groupGL);\n this._camera = coordSys.viewGL.camera;\n } else {\n if (process.env.NODE_ENV !== 'production') {\n throw new Error('Invalid coordinate system');\n }\n }\n\n this.groupGL.removeAll();\n this._currentStep = 0;\n },\n incrementalRender: function (params, seriesModel, ecModel, api) {\n // TODO Sort transparency.\n if (params.end <= params.start) {\n return;\n }\n\n var pointsBuilder = this._pointsBuilderList[this._currentStep];\n\n if (!pointsBuilder) {\n pointsBuilder = new PointsBuilder(false, api);\n this._pointsBuilderList[this._currentStep] = pointsBuilder;\n }\n\n this.groupGL.add(pointsBuilder.rootNode);\n pointsBuilder.update(seriesModel, ecModel, api, params.start, params.end);\n pointsBuilder.updateView(seriesModel.coordinateSystem.viewGL.camera);\n this._currentStep++;\n },\n updateCamera: function () {\n this._pointsBuilderList.forEach(function (pointsBuilder) {\n pointsBuilder.updateView(this._camera);\n }, this);\n },\n highlight: function (seriesModel, ecModel, api, payload) {\n this._toggleStatus('highlight', seriesModel, ecModel, api, payload);\n },\n downplay: function (seriesModel, ecModel, api, payload) {\n this._toggleStatus('downplay', seriesModel, ecModel, api, payload);\n },\n _toggleStatus: function (status, seriesModel, ecModel, api, payload) {\n var data = seriesModel.getData();\n var dataIndex = retrieve.queryDataIndex(data, payload);\n var isHighlight = status === 'highlight';\n\n if (dataIndex != null) {\n echarts.util.each(format.normalizeToArray(dataIndex), function (dataIdx) {\n for (var i = 0; i < this._pointsBuilderList.length; i++) {\n var pointsBuilder = this._pointsBuilderList[i];\n isHighlight ? pointsBuilder.highlight(data, dataIdx) : pointsBuilder.downplay(data, dataIdx);\n }\n }, this);\n } else {\n // PENDING, OPTIMIZE\n data.each(function (dataIdx) {\n for (var i = 0; i < this._pointsBuilderList.length; i++) {\n var pointsBuilder = this._pointsBuilderList[i];\n isHighlight ? pointsBuilder.highlight(data, dataIdx) : pointsBuilder.downplay(data, dataIdx);\n }\n });\n }\n },\n dispose: function () {\n this._pointsBuilderList.forEach(function (pointsBuilder) {\n pointsBuilder.dispose();\n });\n\n this.groupGL.removeAll();\n },\n remove: function () {\n this.groupGL.removeAll();\n }\n});","// TODO ECharts GL must be imported whatever component,charts is imported.\nimport '../../echarts-gl';\nimport Scatter3DSeries from './Scatter3DSeries';\nimport Scatter3DView from './Scatter3DView';\nexport function install(registers) {\n registers.registerChartView(Scatter3DView);\n registers.registerSeriesModel(Scatter3DSeries);\n registers.registerLayout({\n seriesType: 'scatter3D',\n reset: function (seriesModel) {\n var coordSys = seriesModel.coordinateSystem;\n\n if (coordSys) {\n var coordDims = coordSys.dimensions;\n\n if (coordDims.length < 3) {\n if (process.env.NODE_ENV !== 'production') {\n console.error('scatter3D needs 3D coordinateSystem');\n }\n\n return;\n }\n\n var dims = coordDims.map(function (coordDim) {\n return seriesModel.coordDimToDataDim(coordDim)[0];\n });\n var item = [];\n var out = [];\n return {\n progress: function (params, data) {\n var points = new Float32Array((params.end - params.start) * 3);\n\n for (var idx = params.start; idx < params.end; idx++) {\n var idx3 = (idx - params.start) * 3;\n item[0] = data.get(dims[0], idx);\n item[1] = data.get(dims[1], idx);\n item[2] = data.get(dims[2], idx);\n coordSys.dataToPoint(item, out);\n points[idx3] = out[0];\n points[idx3 + 1] = out[1];\n points[idx3 + 2] = out[2];\n }\n\n data.setLayout('points', points);\n }\n };\n }\n }\n });\n}","import { use } from 'echarts/lib/echarts';\nimport { install } from './scatter3D/install';\nuse(install);","import * as echarts from 'echarts/lib/echarts';\nimport glmatrix from 'claygl/src/dep/glmatrix';\nvar vec3 = glmatrix.vec3;\nvar vec2 = glmatrix.vec2;\nvar normalize = vec3.normalize;\nvar cross = vec3.cross;\nvar sub = vec3.sub;\nvar add = vec3.add;\nvar create = vec3.create;\nvar normal = create();\nvar tangent = create();\nvar bitangent = create();\nvar halfVector = create();\nvar coord0 = [];\nvar coord1 = [];\n\nfunction getCubicPointsOnGlobe(coords, coordSys) {\n vec2.copy(coord0, coords[0]);\n vec2.copy(coord1, coords[1]);\n var pts = [];\n var p0 = pts[0] = create();\n var p1 = pts[1] = create();\n var p2 = pts[2] = create();\n var p3 = pts[3] = create();\n coordSys.dataToPoint(coord0, p0);\n coordSys.dataToPoint(coord1, p3); // Get p1\n\n normalize(normal, p0); // TODO p0-p3 is parallel with normal\n\n sub(tangent, p3, p0);\n normalize(tangent, tangent);\n cross(bitangent, tangent, normal);\n normalize(bitangent, bitangent);\n cross(tangent, normal, bitangent); // p1 is half vector of p0 and tangent on p0\n\n add(p1, normal, tangent);\n normalize(p1, p1); // Get p2\n\n normalize(normal, p3);\n sub(tangent, p0, p3);\n normalize(tangent, tangent);\n cross(bitangent, tangent, normal);\n normalize(bitangent, bitangent);\n cross(tangent, normal, bitangent); // p2 is half vector of p3 and tangent on p3\n\n add(p2, normal, tangent);\n normalize(p2, p2); // Project distance of p0 on halfVector\n\n add(halfVector, p0, p3);\n normalize(halfVector, halfVector);\n var projDist = vec3.dot(p0, halfVector); // Angle of halfVector and p1\n\n var cosTheta = vec3.dot(halfVector, p1);\n var len = (Math.max(vec3.len(p0), vec3.len(p3)) - projDist) / cosTheta * 2;\n vec3.scaleAndAdd(p1, p0, p1, len);\n vec3.scaleAndAdd(p2, p3, p2, len);\n return pts;\n}\n\nfunction getCubicPointsOnPlane(coords, coordSys, up) {\n var pts = [];\n var p0 = pts[0] = vec3.create();\n var p1 = pts[1] = vec3.create();\n var p2 = pts[2] = vec3.create();\n var p3 = pts[3] = vec3.create();\n coordSys.dataToPoint(coords[0], p0);\n coordSys.dataToPoint(coords[1], p3);\n var len = vec3.dist(p0, p3);\n vec3.lerp(p1, p0, p3, 0.3);\n vec3.lerp(p2, p0, p3, 0.3);\n vec3.scaleAndAdd(p1, p1, up, Math.min(len * 0.1, 10));\n vec3.scaleAndAdd(p2, p2, up, Math.min(len * 0.1, 10));\n return pts;\n}\n\nfunction getPolylinePoints(coords, coordSys) {\n var pts = new Float32Array(coords.length * 3);\n var off = 0;\n var pt = [];\n\n for (var i = 0; i < coords.length; i++) {\n coordSys.dataToPoint(coords[i], pt);\n pts[off++] = pt[0];\n pts[off++] = pt[1];\n pts[off++] = pt[2];\n }\n\n return pts;\n}\n\nfunction prepareCoords(data) {\n var coordsList = [];\n data.each(function (idx) {\n var itemModel = data.getItemModel(idx);\n var coords = itemModel.option instanceof Array ? itemModel.option : itemModel.getShallow('coords', true);\n\n if (process.env.NODE_ENV !== 'production') {\n if (!(coords instanceof Array && coords.length > 0 && coords[0] instanceof Array)) {\n throw new Error('Invalid coords ' + JSON.stringify(coords) + '. Lines must have 2d coords array in data item.');\n }\n }\n\n coordsList.push(coords);\n });\n return {\n coordsList: coordsList\n };\n}\n\nfunction layoutGlobe(seriesModel, coordSys) {\n var data = seriesModel.getData();\n var isPolyline = seriesModel.get('polyline');\n data.setLayout('lineType', isPolyline ? 'polyline' : 'cubicBezier');\n var res = prepareCoords(data);\n data.each(function (idx) {\n var coords = res.coordsList[idx];\n var getPointsMethod = isPolyline ? getPolylinePoints : getCubicPointsOnGlobe;\n data.setItemLayout(idx, getPointsMethod(coords, coordSys));\n });\n}\n\nfunction layoutOnPlane(seriesModel, coordSys, normal) {\n var data = seriesModel.getData();\n var isPolyline = seriesModel.get('polyline');\n var res = prepareCoords(data);\n data.setLayout('lineType', isPolyline ? 'polyline' : 'cubicBezier');\n data.each(function (idx) {\n var coords = res.coordsList[idx];\n var pts = isPolyline ? getPolylinePoints(coords, coordSys) : getCubicPointsOnPlane(coords, coordSys, normal);\n data.setItemLayout(idx, pts);\n });\n}\n\nexport default function lines3DLayout(ecModel, api) {\n ecModel.eachSeriesByType('lines3D', function (seriesModel) {\n var coordSys = seriesModel.coordinateSystem;\n\n if (coordSys.type === 'globe') {\n layoutGlobe(seriesModel, coordSys);\n } else if (coordSys.type === 'geo3D') {\n layoutOnPlane(seriesModel, coordSys, [0, 1, 0]);\n } else if (coordSys.type === 'mapbox3D' || coordSys.type === 'maptalks3D') {\n layoutOnPlane(seriesModel, coordSys, [0, 0, 1]);\n }\n });\n}\n;","import * as echarts from 'echarts/lib/echarts';\nexport default echarts.SeriesModel.extend({\n type: 'series.lines3D',\n dependencies: ['globe'],\n visualStyleAccessPath: 'lineStyle',\n visualDrawType: 'stroke',\n getInitialData: function (option, ecModel) {\n var lineData = new echarts.List(['value'], this);\n lineData.hasItemOption = false;\n lineData.initData(option.data, [], function (dataItem, dimName, dataIndex, dimIndex) {\n // dataItem is simply coords\n if (dataItem instanceof Array) {\n return NaN;\n } else {\n lineData.hasItemOption = true;\n var value = dataItem.value;\n\n if (value != null) {\n return value instanceof Array ? value[dimIndex] : value;\n }\n }\n });\n return lineData;\n },\n defaultOption: {\n coordinateSystem: 'globe',\n globeIndex: 0,\n geo3DIndex: 0,\n zlevel: -10,\n polyline: false,\n effect: {\n show: false,\n period: 4,\n // Trail width\n trailWidth: 4,\n trailLength: 0.2,\n spotIntensity: 6\n },\n silent: true,\n // Support source-over, lighter\n blendMode: 'source-over',\n lineStyle: {\n width: 1,\n opacity: 0.5 // color\n\n }\n }\n});","export default \"@export ecgl.trail2.vertex\\nattribute vec3 position: POSITION;\\nattribute vec3 positionPrev;\\nattribute vec3 positionNext;\\nattribute float offset;\\nattribute float dist;\\nattribute float distAll;\\nattribute float start;\\n\\nattribute vec4 a_Color : COLOR;\\n\\nuniform mat4 worldViewProjection : WORLDVIEWPROJECTION;\\nuniform vec4 viewport : VIEWPORT;\\nuniform float near : NEAR;\\n\\nuniform float speed : 0;\\nuniform float trailLength: 0.3;\\nuniform float time;\\nuniform float period: 1000;\\n\\nuniform float spotSize: 1;\\n\\nvarying vec4 v_Color;\\nvarying float v_Percent;\\nvarying float v_SpotPercent;\\n\\n@import ecgl.common.wireframe.vertexHeader\\n\\n@import ecgl.lines3D.clipNear\\n\\nvoid main()\\n{\\n @import ecgl.lines3D.expandLine\\n\\n gl_Position = currProj;\\n\\n v_Color = a_Color;\\n\\n @import ecgl.common.wireframe.vertexMain\\n\\n#ifdef CONSTANT_SPEED\\n float t = mod((speed * time + start) / distAll, 1. + trailLength) - trailLength;\\n#else\\n float t = mod((time + start) / period, 1. + trailLength) - trailLength;\\n#endif\\n\\n float trailLen = distAll * trailLength;\\n\\n v_Percent = (dist - t * distAll) / trailLen;\\n\\n v_SpotPercent = spotSize / distAll;\\n\\n }\\n@end\\n\\n\\n@export ecgl.trail2.fragment\\n\\nuniform vec4 color : [1.0, 1.0, 1.0, 1.0];\\nuniform float spotIntensity: 5;\\n\\nvarying vec4 v_Color;\\nvarying float v_Percent;\\nvarying float v_SpotPercent;\\n\\n@import ecgl.common.wireframe.fragmentHeader\\n\\n@import clay.util.srgb\\n\\nvoid main()\\n{\\n if (v_Percent > 1.0 || v_Percent < 0.0) {\\n discard;\\n }\\n\\n float fade = v_Percent;\\n\\n#ifdef SRGB_DECODE\\n gl_FragColor = sRGBToLinear(color * v_Color);\\n#else\\n gl_FragColor = color * v_Color;\\n#endif\\n\\n @import ecgl.common.wireframe.fragmentMain\\n\\n if (v_Percent > (1.0 - v_SpotPercent)) {\\n gl_FragColor.rgb *= spotIntensity;\\n }\\n\\n gl_FragColor.a *= fade;\\n}\\n\\n@end\";","import * as echarts from 'echarts/lib/echarts';\nimport graphicGL from '../../util/graphicGL';\nimport glmatrix from 'claygl/src/dep/glmatrix';\nimport Lines3DGeometry from '../../util/geometry/Lines3D';\nimport trail2GLSL from './shader/trail2.glsl.js';\nimport { getItemVisualColor, getItemVisualOpacity } from '../../util/visual';\nvar vec3 = glmatrix.vec3;\n\nfunction sign(a) {\n return a > 0 ? 1 : -1;\n}\n\ngraphicGL.Shader.import(trail2GLSL);\nexport default graphicGL.Mesh.extend(function () {\n var material = new graphicGL.Material({\n shader: new graphicGL.Shader(graphicGL.Shader.source('ecgl.trail2.vertex'), graphicGL.Shader.source('ecgl.trail2.fragment')),\n transparent: true,\n depthMask: false\n });\n var geometry = new Lines3DGeometry({\n dynamic: true\n });\n geometry.createAttribute('dist', 'float', 1);\n geometry.createAttribute('distAll', 'float', 1);\n geometry.createAttribute('start', 'float', 1);\n return {\n geometry: geometry,\n material: material,\n culling: false,\n $ignorePicking: true\n };\n}, {\n updateData: function (data, api, lines3DGeometry) {\n var seriesModel = data.hostModel;\n var geometry = this.geometry;\n var effectModel = seriesModel.getModel('effect');\n var size = effectModel.get('trailWidth') * api.getDevicePixelRatio();\n var trailLength = effectModel.get('trailLength');\n var speed = seriesModel.get('effect.constantSpeed');\n var period = seriesModel.get('effect.period') * 1000;\n var useConstantSpeed = speed != null;\n\n if (process.env.NODE_ENV !== 'production') {\n if (!this.getScene()) {\n console.error('TrailMesh must been add to scene before updateData');\n }\n }\n\n useConstantSpeed ? this.material.set('speed', speed / 1000) : this.material.set('period', period);\n this.material[useConstantSpeed ? 'define' : 'undefine']('vertex', 'CONSTANT_SPEED');\n var isPolyline = seriesModel.get('polyline');\n geometry.trailLength = trailLength;\n this.material.set('trailLength', trailLength);\n geometry.resetOffset();\n ['position', 'positionPrev', 'positionNext'].forEach(function (attrName) {\n geometry.attributes[attrName].value = lines3DGeometry.attributes[attrName].value;\n });\n var extraAttrs = ['dist', 'distAll', 'start', 'offset', 'color'];\n extraAttrs.forEach(function (attrName) {\n geometry.attributes[attrName].init(geometry.vertexCount);\n });\n geometry.indices = lines3DGeometry.indices;\n var colorArr = [];\n var effectColor = effectModel.get('trailColor');\n var effectOpacity = effectModel.get('trailOpacity');\n var hasEffectColor = effectColor != null;\n var hasEffectOpacity = effectOpacity != null;\n this.updateWorldTransform();\n var xScale = this.worldTransform.x.len();\n var yScale = this.worldTransform.y.len();\n var zScale = this.worldTransform.z.len();\n var vertexOffset = 0;\n var maxDistance = 0;\n data.each(function (idx) {\n var pts = data.getItemLayout(idx);\n var opacity = hasEffectOpacity ? effectOpacity : getItemVisualOpacity(data, idx);\n var color = getItemVisualColor(data, idx);\n\n if (opacity == null) {\n opacity = 1;\n }\n\n colorArr = graphicGL.parseColor(hasEffectColor ? effectColor : color, colorArr);\n colorArr[3] *= opacity;\n var vertexCount = isPolyline ? lines3DGeometry.getPolylineVertexCount(pts) : lines3DGeometry.getCubicCurveVertexCount(pts[0], pts[1], pts[2], pts[3]);\n var dist = 0;\n var pos = [];\n var posPrev = [];\n\n for (var i = vertexOffset; i < vertexOffset + vertexCount; i++) {\n geometry.attributes.position.get(i, pos);\n pos[0] *= xScale;\n pos[1] *= yScale;\n pos[2] *= zScale;\n\n if (i > vertexOffset) {\n dist += vec3.dist(pos, posPrev);\n }\n\n geometry.attributes.dist.set(i, dist);\n vec3.copy(posPrev, pos);\n }\n\n maxDistance = Math.max(maxDistance, dist);\n var randomStart = Math.random() * (useConstantSpeed ? dist : period);\n\n for (var i = vertexOffset; i < vertexOffset + vertexCount; i++) {\n geometry.attributes.distAll.set(i, dist);\n geometry.attributes.start.set(i, randomStart);\n geometry.attributes.offset.set(i, sign(lines3DGeometry.attributes.offset.get(i)) * size / 2);\n geometry.attributes.color.set(i, colorArr);\n }\n\n vertexOffset += vertexCount;\n });\n this.material.set('spotSize', maxDistance * 0.1 * trailLength);\n this.material.set('spotIntensity', effectModel.get('spotIntensity'));\n geometry.dirty();\n },\n setAnimationTime: function (time) {\n this.material.set('time', time);\n }\n});","import * as echarts from 'echarts/lib/echarts';\nimport graphicGL from '../../util/graphicGL';\nimport LinesGeometry from '../../util/geometry/Lines3D'; // import TrailMesh from './TrailMesh';\n\nimport TrailMesh2 from './TrailMesh2';\nimport { getItemVisualColor, getItemVisualOpacity } from '../../util/visual';\nimport lines3DGLSL from '../../util/shader/lines3D.glsl.js';\ngraphicGL.Shader.import(lines3DGLSL);\n\nfunction getCoordSysSize(coordSys) {\n if (coordSys.radius != null) {\n return coordSys.radius;\n }\n\n if (coordSys.size != null) {\n return Math.max(coordSys.size[0], coordSys.size[1], coordSys.size[2]);\n } else {\n return 100;\n }\n}\n\nexport default echarts.ChartView.extend({\n type: 'lines3D',\n __ecgl__: true,\n init: function (ecModel, api) {\n this.groupGL = new graphicGL.Node();\n this._meshLinesMaterial = new graphicGL.Material({\n shader: graphicGL.createShader('ecgl.meshLines3D'),\n transparent: true,\n depthMask: false\n });\n this._linesMesh = new graphicGL.Mesh({\n geometry: new LinesGeometry(),\n material: this._meshLinesMaterial,\n $ignorePicking: true\n }); // this._trailMesh = new TrailMesh();\n\n this._trailMesh = new TrailMesh2();\n },\n render: function (seriesModel, ecModel, api) {\n this.groupGL.add(this._linesMesh);\n var coordSys = seriesModel.coordinateSystem;\n var data = seriesModel.getData();\n\n if (coordSys && coordSys.viewGL) {\n var viewGL = coordSys.viewGL;\n viewGL.add(this.groupGL);\n\n this._updateLines(seriesModel, ecModel, api);\n\n var methodName = coordSys.viewGL.isLinearSpace() ? 'define' : 'undefine';\n\n this._linesMesh.material[methodName]('fragment', 'SRGB_DECODE');\n\n this._trailMesh.material[methodName]('fragment', 'SRGB_DECODE');\n }\n\n var trailMesh = this._trailMesh;\n trailMesh.stopAnimation();\n\n if (seriesModel.get('effect.show')) {\n this.groupGL.add(trailMesh);\n trailMesh.updateData(data, api, this._linesMesh.geometry);\n trailMesh.__time = trailMesh.__time || 0;\n var time = 3600 * 1000; // 1hour\n\n this._curveEffectsAnimator = trailMesh.animate('', {\n loop: true\n }).when(time, {\n __time: time\n }).during(function () {\n trailMesh.setAnimationTime(trailMesh.__time);\n }).start();\n } else {\n this.groupGL.remove(trailMesh);\n this._curveEffectsAnimator = null;\n }\n\n this._linesMesh.material.blend = this._trailMesh.material.blend = seriesModel.get('blendMode') === 'lighter' ? graphicGL.additiveBlend : null;\n },\n pauseEffect: function () {\n if (this._curveEffectsAnimator) {\n this._curveEffectsAnimator.pause();\n }\n },\n resumeEffect: function () {\n if (this._curveEffectsAnimator) {\n this._curveEffectsAnimator.resume();\n }\n },\n toggleEffect: function () {\n var animator = this._curveEffectsAnimator;\n\n if (animator) {\n animator.isPaused() ? animator.resume() : animator.pause();\n }\n },\n _updateLines: function (seriesModel, ecModel, api) {\n var data = seriesModel.getData();\n var coordSys = seriesModel.coordinateSystem;\n var geometry = this._linesMesh.geometry;\n var isPolyline = seriesModel.get('polyline');\n geometry.expandLine = true;\n var size = getCoordSysSize(coordSys);\n geometry.segmentScale = size / 20;\n var lineWidthQueryPath = 'lineStyle.width'.split('.');\n var dpr = api.getDevicePixelRatio();\n var maxLineWidth = 0;\n data.each(function (idx) {\n var itemModel = data.getItemModel(idx);\n var lineWidth = itemModel.get(lineWidthQueryPath);\n\n if (lineWidth == null) {\n lineWidth = 1;\n }\n\n data.setItemVisual(idx, 'lineWidth', lineWidth);\n maxLineWidth = Math.max(lineWidth, maxLineWidth);\n }); // Must set useNativeLine before calling any other methods\n\n geometry.useNativeLine = false;\n var nVertex = 0;\n var nTriangle = 0;\n data.each(function (idx) {\n var pts = data.getItemLayout(idx);\n\n if (isPolyline) {\n nVertex += geometry.getPolylineVertexCount(pts);\n nTriangle += geometry.getPolylineTriangleCount(pts);\n } else {\n nVertex += geometry.getCubicCurveVertexCount(pts[0], pts[1], pts[2], pts[3]);\n nTriangle += geometry.getCubicCurveTriangleCount(pts[0], pts[1], pts[2], pts[3]);\n }\n });\n geometry.setVertexCount(nVertex);\n geometry.setTriangleCount(nTriangle);\n geometry.resetOffset();\n var colorArr = [];\n data.each(function (idx) {\n var pts = data.getItemLayout(idx);\n var color = getItemVisualColor(data, idx);\n var opacity = getItemVisualOpacity(data, idx);\n var lineWidth = data.getItemVisual(idx, 'lineWidth') * dpr;\n\n if (opacity == null) {\n opacity = 1;\n }\n\n colorArr = graphicGL.parseColor(color, colorArr);\n colorArr[3] *= opacity;\n\n if (isPolyline) {\n geometry.addPolyline(pts, colorArr, lineWidth);\n } else {\n geometry.addCubicCurve(pts[0], pts[1], pts[2], pts[3], colorArr, lineWidth);\n }\n });\n geometry.dirty();\n },\n remove: function () {\n this.groupGL.removeAll();\n },\n dispose: function () {\n this.groupGL.removeAll();\n }\n});","// TODO ECharts GL must be imported whatever component,charts is imported.\nimport '../../echarts-gl';\nimport lines3DLayout from './lines3DLayout';\nimport Lines3DSeries from './Lines3DSeries';\nimport Lines3DView from './Lines3DView';\nexport function install(registers) {\n registers.registerChartView(Lines3DView);\n registers.registerSeriesModel(Lines3DSeries);\n registers.registerLayout(lines3DLayout);\n registers.registerAction({\n type: 'lines3DPauseEffect',\n event: 'lines3deffectpaused',\n update: 'series.lines3D:pauseEffect'\n }, function () {});\n registers.registerAction({\n type: 'lines3DResumeEffect',\n event: 'lines3deffectresumed',\n update: 'series.lines3D:resumeEffect'\n }, function () {});\n registers.registerAction({\n type: 'lines3DToggleEffect',\n event: 'lines3deffectchanged',\n update: 'series.lines3D:toggleEffect'\n }, function () {});\n}","import * as echarts from 'echarts/lib/echarts';\nimport componentShadingMixin from '../../component/common/componentShadingMixin';\n\nfunction transformPolygon(coordSys, poly) {\n var ret = [];\n\n for (var i = 0; i < poly.length; i++) {\n ret.push(coordSys.dataToPoint(poly[i]));\n }\n\n return ret;\n}\n\nvar Polygons3DSeries = echarts.SeriesModel.extend({\n type: 'series.polygons3D',\n getRegionModel: function (idx) {\n return this.getData().getItemModel(idx);\n },\n getRegionPolygonCoords: function (idx) {\n var coordSys = this.coordinateSystem;\n var itemModel = this.getData().getItemModel(idx);\n var coords = itemModel.option instanceof Array ? itemModel.option : itemModel.getShallow('coords');\n\n if (!itemModel.get('multiPolygon')) {\n coords = [coords];\n } // TODO Validate\n\n\n var out = [];\n\n for (var i = 0; i < coords.length; i++) {\n // TODO Convert here ?\n var interiors = [];\n\n for (var k = 1; k < coords[i].length; k++) {\n interiors.push(transformPolygon(coordSys, coords[i][k]));\n }\n\n out.push({\n exterior: transformPolygon(coordSys, coords[i][0]),\n interiors: interiors\n });\n }\n\n return out;\n },\n getInitialData: function (option) {\n var polygonsData = new echarts.List(['value'], this);\n polygonsData.hasItemOption = false;\n polygonsData.initData(option.data, [], function (dataItem, dimName, dataIndex, dimIndex) {\n // dataItem is simply coords\n if (dataItem instanceof Array) {\n return NaN;\n } else {\n polygonsData.hasItemOption = true;\n var value = dataItem.value;\n\n if (value != null) {\n return value instanceof Array ? value[dimIndex] : value;\n }\n }\n });\n return polygonsData;\n },\n defaultOption: {\n show: true,\n data: null,\n multiPolygon: false,\n progressiveThreshold: 1e3,\n progressive: 1e3,\n zlevel: -10,\n label: {\n show: false,\n // Distance in 3d space.\n distance: 2,\n textStyle: {\n fontSize: 20,\n color: '#000',\n backgroundColor: 'rgba(255,255,255,0.7)',\n padding: 3,\n borderRadius: 4\n }\n },\n itemStyle: {\n color: '#fff',\n borderWidth: 0,\n borderColor: '#333'\n },\n emphasis: {\n itemStyle: {\n color: '#639fc0'\n },\n label: {\n show: true\n }\n }\n }\n});\necharts.util.merge(Polygons3DSeries.prototype, componentShadingMixin);\nexport default Polygons3DSeries;","import { use } from 'echarts/lib/echarts';\nimport { install } from './lines3D/install';\nuse(install);","import * as echarts from 'echarts/lib/echarts';\nimport Geo3DBuilder from '../../component/common/Geo3DBuilder';\nimport graphicGL from '../../util/graphicGL';\nexport default echarts.ChartView.extend({\n type: 'polygons3D',\n __ecgl__: true,\n init: function (ecModel, api) {\n this.groupGL = new graphicGL.Node();\n this._geo3DBuilderList = [];\n this._currentStep = 0;\n },\n render: function (seriesModel, ecModel, api) {\n this.groupGL.removeAll();\n var coordSys = seriesModel.coordinateSystem;\n\n if (coordSys && coordSys.viewGL) {\n coordSys.viewGL.add(this.groupGL);\n }\n\n var geo3DBuilder = this._geo3DBuilderList[0];\n\n if (!geo3DBuilder) {\n geo3DBuilder = new Geo3DBuilder(api);\n geo3DBuilder.extrudeY = coordSys.type !== 'mapbox3D' && coordSys.type !== 'maptalks3D';\n this._geo3DBuilderList[0] = geo3DBuilder;\n }\n\n this._updateShaderDefines(coordSys, geo3DBuilder);\n\n geo3DBuilder.update(seriesModel, ecModel, api);\n this._geo3DBuilderList.length = 1;\n this.groupGL.add(geo3DBuilder.rootNode);\n },\n incrementalPrepareRender: function (seriesModel, ecModel, api) {\n this.groupGL.removeAll();\n var coordSys = seriesModel.coordinateSystem;\n\n if (coordSys && coordSys.viewGL) {\n coordSys.viewGL.add(this.groupGL);\n }\n\n this._currentStep = 0;\n },\n incrementalRender: function (params, seriesModel, ecModel, api) {\n var geo3DBuilder = this._geo3DBuilderList[this._currentStep];\n var coordSys = seriesModel.coordinateSystem;\n\n if (!geo3DBuilder) {\n geo3DBuilder = new Geo3DBuilder(api);\n geo3DBuilder.extrudeY = coordSys.type !== 'mapbox3D' && coordSys.type !== 'maptalks3D';\n this._geo3DBuilderList[this._currentStep] = geo3DBuilder;\n }\n\n geo3DBuilder.update(seriesModel, ecModel, api, params.start, params.end);\n this.groupGL.add(geo3DBuilder.rootNode);\n\n this._updateShaderDefines(coordSys, geo3DBuilder);\n\n this._currentStep++;\n },\n _updateShaderDefines: function (coordSys, geo3DBuilder) {\n var methodName = coordSys.viewGL.isLinearSpace() ? 'define' : 'undefine';\n geo3DBuilder.rootNode.traverse(function (mesh) {\n if (mesh.material) {\n mesh.material[methodName]('fragment', 'SRGB_DECODE'); // FIXME\n\n if (coordSys.type === 'mapbox3D' || coordSys.type === 'maptalks3D') {\n mesh.material.define('fragment', 'NORMAL_UP_AXIS', 2);\n mesh.material.define('fragment', 'NORMAL_FRONT_AXIS', 1);\n }\n }\n });\n },\n remove: function () {\n this.groupGL.removeAll();\n },\n dispose: function () {\n this.groupGL.removeAll();\n\n this._geo3DBuilderList.forEach(function (geo3DBuilder) {\n geo3DBuilder.dispose();\n });\n }\n});","// TODO ECharts GL must be imported whatever component,charts is imported.\nimport '../../echarts-gl';\nimport Polygons3DSeries from './Polygons3DSeries';\nimport Polygons3DView from './Polygons3DView';\nexport function install(registers) {\n registers.registerChartView(Polygons3DView);\n registers.registerSeriesModel(Polygons3DSeries);\n}","import { use } from 'echarts/lib/echarts';\nimport { install } from './polygons3D/install';\nuse(install);","import * as echarts from 'echarts/lib/echarts';\nimport componentShadingMixin from '../../component/common/componentShadingMixin';\nimport formatTooltip from '../common/formatTooltip';\nimport createList from '../common/createList';\nvar SurfaceSeries = echarts.SeriesModel.extend({\n type: 'series.surface',\n dependencies: ['globe', 'grid3D', 'geo3D'],\n visualStyleAccessPath: 'itemStyle',\n formatTooltip: function (dataIndex) {\n return formatTooltip(this, dataIndex);\n },\n getInitialData: function (option, ecModel) {\n var data = option.data;\n\n function validateDimension(dimOpts) {\n return !(isNaN(dimOpts.min) || isNaN(dimOpts.max) || isNaN(dimOpts.step));\n }\n\n function getPrecision(dimOpts) {\n var getPrecision = echarts.number.getPrecisionSafe;\n return Math.max(getPrecision(dimOpts.min), getPrecision(dimOpts.max), getPrecision(dimOpts.step)) + 1;\n }\n\n if (!data) {\n if (!option.parametric) {\n // From surface equation\n var equation = option.equation || {};\n var xOpts = equation.x || {};\n var yOpts = equation.y || {};\n ['x', 'y'].forEach(function (dim) {\n if (!validateDimension(equation[dim])) {\n if (process.env.NODE_ENV !== 'production') {\n console.error('Invalid equation.%s', dim);\n }\n\n return;\n }\n });\n\n if (typeof equation.z !== 'function') {\n if (process.env.NODE_ENV !== 'production') {\n console.error('equation.z needs to be function');\n }\n\n return;\n }\n\n var xCount = Math.floor((xOpts.max + xOpts.step - xOpts.min) / xOpts.step);\n var yCount = Math.floor((yOpts.max + yOpts.step - yOpts.min) / yOpts.step);\n data = new Float32Array(xCount * yCount * 3);\n var xPrecision = getPrecision(xOpts);\n var yPrecision = getPrecision(yOpts);\n var off = 0;\n\n for (var j = 0; j < yCount; j++) {\n for (var i = 0; i < xCount; i++) {\n var x = i * xOpts.step + xOpts.min;\n var y = j * yOpts.step + yOpts.min;\n var x2 = echarts.number.round(Math.min(x, xOpts.max), xPrecision);\n var y2 = echarts.number.round(Math.min(y, yOpts.max), yPrecision);\n var z = equation.z(x2, y2);\n data[off++] = x2;\n data[off++] = y2;\n data[off++] = z;\n }\n }\n } else {\n var parametricEquation = option.parametricEquation || {};\n var uOpts = parametricEquation.u || {};\n var vOpts = parametricEquation.v || {};\n ['u', 'v'].forEach(function (dim) {\n if (!validateDimension(parametricEquation[dim])) {\n if (process.env.NODE_ENV !== 'production') {\n console.error('Invalid parametricEquation.%s', dim);\n }\n\n return;\n }\n });\n ['x', 'y', 'z'].forEach(function (dim) {\n if (typeof parametricEquation[dim] !== 'function') {\n if (process.env.NODE_ENV !== 'production') {\n console.error('parametricEquation.%s needs to be function', dim);\n }\n\n return;\n }\n });\n var uCount = Math.floor((uOpts.max + uOpts.step - uOpts.min) / uOpts.step);\n var vCount = Math.floor((vOpts.max + vOpts.step - vOpts.min) / vOpts.step);\n data = new Float32Array(uCount * vCount * 5);\n var uPrecision = getPrecision(uOpts);\n var vPrecision = getPrecision(vOpts);\n var off = 0;\n\n for (var j = 0; j < vCount; j++) {\n for (var i = 0; i < uCount; i++) {\n var u = i * uOpts.step + uOpts.min;\n var v = j * vOpts.step + vOpts.min;\n var u2 = echarts.number.round(Math.min(u, uOpts.max), uPrecision);\n var v2 = echarts.number.round(Math.min(v, vOpts.max), vPrecision);\n var x = parametricEquation.x(u2, v2);\n var y = parametricEquation.y(u2, v2);\n var z = parametricEquation.z(u2, v2);\n data[off++] = x;\n data[off++] = y;\n data[off++] = z;\n data[off++] = u2;\n data[off++] = v2;\n }\n }\n }\n }\n\n var dims = ['x', 'y', 'z'];\n\n if (option.parametric) {\n dims.push('u', 'v');\n } // PENDING getSource?\n\n\n var list = createList(this, dims, data);\n return list;\n },\n defaultOption: {\n coordinateSystem: 'cartesian3D',\n zlevel: -10,\n // Cartesian coordinate system\n grid3DIndex: 0,\n // Surface needs lambert shading to show the difference\n shading: 'lambert',\n // If parametric surface\n parametric: false,\n wireframe: {\n show: true,\n lineStyle: {\n color: 'rgba(0,0,0,0.5)',\n width: 1\n }\n },\n\n /**\n * Generate surface data from z = f(x, y) equation\n */\n equation: {\n // [min, max, step]\n x: {\n min: -1,\n max: 1,\n step: 0.1\n },\n y: {\n min: -1,\n max: 1,\n step: 0.1\n },\n z: null\n },\n parametricEquation: {\n // [min, max, step]\n u: {\n min: -1,\n max: 1,\n step: 0.1\n },\n v: {\n min: -1,\n max: 1,\n step: 0.1\n },\n // [x, y, z] = f(x, y)\n x: null,\n y: null,\n z: null\n },\n // Shape of give data\n // It is an array to specify rows and columns.\n // For example [30, 30]\n dataShape: null,\n itemStyle: {// Color\n },\n animationDurationUpdate: 500\n }\n});\necharts.util.merge(SurfaceSeries.prototype, componentShadingMixin);\nexport default SurfaceSeries;","import * as echarts from 'echarts/lib/echarts';\nimport graphicGL from '../../util/graphicGL';\nimport glmatrix from 'claygl/src/dep/glmatrix';\nimport trianglesSortMixin from '../../util/geometry/trianglesSortMixin';\nimport { getItemVisualColor, getItemVisualOpacity } from '../../util/visual';\nvar vec3 = glmatrix.vec3;\n\nfunction isPointsNaN(pt) {\n return isNaN(pt[0]) || isNaN(pt[1]) || isNaN(pt[2]);\n}\n\nexport default echarts.ChartView.extend({\n type: 'surface',\n __ecgl__: true,\n init: function (ecModel, api) {\n this.groupGL = new graphicGL.Node();\n },\n render: function (seriesModel, ecModel, api) {\n // Swap surfaceMesh\n var tmp = this._prevSurfaceMesh;\n this._prevSurfaceMesh = this._surfaceMesh;\n this._surfaceMesh = tmp;\n\n if (!this._surfaceMesh) {\n this._surfaceMesh = this._createSurfaceMesh();\n }\n\n this.groupGL.remove(this._prevSurfaceMesh);\n this.groupGL.add(this._surfaceMesh);\n var coordSys = seriesModel.coordinateSystem;\n var shading = seriesModel.get('shading');\n var data = seriesModel.getData();\n var shadingPrefix = 'ecgl.' + shading;\n\n if (!this._surfaceMesh.material || this._surfaceMesh.material.shader.name !== shadingPrefix) {\n this._surfaceMesh.material = graphicGL.createMaterial(shadingPrefix, ['VERTEX_COLOR', 'DOUBLE_SIDED']);\n }\n\n graphicGL.setMaterialFromModel(shading, this._surfaceMesh.material, seriesModel, api);\n\n if (coordSys && coordSys.viewGL) {\n coordSys.viewGL.add(this.groupGL);\n var methodName = coordSys.viewGL.isLinearSpace() ? 'define' : 'undefine';\n\n this._surfaceMesh.material[methodName]('fragment', 'SRGB_DECODE');\n }\n\n var isParametric = seriesModel.get('parametric');\n var dataShape = seriesModel.get('dataShape');\n\n if (!dataShape) {\n dataShape = this._getDataShape(data, isParametric);\n\n if (process.env.NODE_ENV !== 'production') {\n if (seriesModel.get('data')) {\n console.warn('dataShape is not provided. Guess it is ', dataShape);\n }\n }\n }\n\n var wireframeModel = seriesModel.getModel('wireframe');\n var wireframeLineWidth = wireframeModel.get('lineStyle.width');\n var showWireframe = wireframeModel.get('show') && wireframeLineWidth > 0;\n\n this._updateSurfaceMesh(this._surfaceMesh, seriesModel, dataShape, showWireframe);\n\n var material = this._surfaceMesh.material;\n\n if (showWireframe) {\n material.define('WIREFRAME_QUAD');\n material.set('wireframeLineWidth', wireframeLineWidth);\n material.set('wireframeLineColor', graphicGL.parseColor(wireframeModel.get('lineStyle.color')));\n } else {\n material.undefine('WIREFRAME_QUAD');\n }\n\n this._initHandler(seriesModel, api);\n\n this._updateAnimation(seriesModel);\n },\n _updateAnimation: function (seriesModel) {\n graphicGL.updateVertexAnimation([['prevPosition', 'position'], ['prevNormal', 'normal']], this._prevSurfaceMesh, this._surfaceMesh, seriesModel);\n },\n _createSurfaceMesh: function () {\n var mesh = new graphicGL.Mesh({\n geometry: new graphicGL.Geometry({\n dynamic: true,\n sortTriangles: true\n }),\n shadowDepthMaterial: new graphicGL.Material({\n shader: new graphicGL.Shader(graphicGL.Shader.source('ecgl.sm.depth.vertex'), graphicGL.Shader.source('ecgl.sm.depth.fragment'))\n }),\n culling: false,\n // Render after axes\n renderOrder: 10,\n // Render normal in normal pass\n renderNormal: true\n });\n mesh.geometry.createAttribute('barycentric', 'float', 4);\n mesh.geometry.createAttribute('prevPosition', 'float', 3);\n mesh.geometry.createAttribute('prevNormal', 'float', 3);\n Object.assign(mesh.geometry, trianglesSortMixin);\n return mesh;\n },\n _initHandler: function (seriesModel, api) {\n var data = seriesModel.getData();\n var surfaceMesh = this._surfaceMesh;\n var coordSys = seriesModel.coordinateSystem;\n\n function getNearestPointIdx(triangle, point) {\n var nearestDist = Infinity;\n var nearestIdx = -1;\n var pos = [];\n\n for (var i = 0; i < triangle.length; i++) {\n surfaceMesh.geometry.attributes.position.get(triangle[i], pos);\n var dist = vec3.dist(point.array, pos);\n\n if (dist < nearestDist) {\n nearestDist = dist;\n nearestIdx = triangle[i];\n }\n }\n\n return nearestIdx;\n }\n\n surfaceMesh.seriesIndex = seriesModel.seriesIndex;\n var lastDataIndex = -1;\n surfaceMesh.off('mousemove');\n surfaceMesh.off('mouseout');\n surfaceMesh.on('mousemove', function (e) {\n var idx = getNearestPointIdx(e.triangle, e.point);\n\n if (idx >= 0) {\n var point = [];\n surfaceMesh.geometry.attributes.position.get(idx, point);\n var value = coordSys.pointToData(point);\n var minDist = Infinity;\n var dataIndex = -1;\n var item = [];\n\n for (var i = 0; i < data.count(); i++) {\n item[0] = data.get('x', i);\n item[1] = data.get('y', i);\n item[2] = data.get('z', i);\n var dist = vec3.squaredDistance(item, value);\n\n if (dist < minDist) {\n dataIndex = i;\n minDist = dist;\n }\n }\n\n if (dataIndex !== lastDataIndex) {\n api.dispatchAction({\n type: 'grid3DShowAxisPointer',\n value: value\n });\n }\n\n lastDataIndex = dataIndex;\n surfaceMesh.dataIndex = dataIndex;\n } else {\n surfaceMesh.dataIndex = -1;\n }\n }, this);\n surfaceMesh.on('mouseout', function (e) {\n lastDataIndex = -1;\n surfaceMesh.dataIndex = -1;\n api.dispatchAction({\n type: 'grid3DHideAxisPointer'\n });\n }, this);\n },\n _updateSurfaceMesh: function (surfaceMesh, seriesModel, dataShape, showWireframe) {\n var geometry = surfaceMesh.geometry;\n var data = seriesModel.getData();\n var pointsArr = data.getLayout('points');\n var invalidDataCount = 0;\n data.each(function (idx) {\n if (!data.hasValue(idx)) {\n invalidDataCount++;\n }\n });\n var needsSplitQuad = invalidDataCount || showWireframe;\n var positionAttr = geometry.attributes.position;\n var normalAttr = geometry.attributes.normal;\n var texcoordAttr = geometry.attributes.texcoord0;\n var barycentricAttr = geometry.attributes.barycentric;\n var colorAttr = geometry.attributes.color;\n var row = dataShape[0];\n var column = dataShape[1];\n var shading = seriesModel.get('shading');\n var needsNormal = shading !== 'color';\n\n if (needsSplitQuad) {\n // TODO, If needs remove the invalid points, or set color transparent.\n var vertexCount = (row - 1) * (column - 1) * 4;\n positionAttr.init(vertexCount);\n\n if (showWireframe) {\n barycentricAttr.init(vertexCount);\n }\n } else {\n positionAttr.value = new Float32Array(pointsArr);\n }\n\n colorAttr.init(geometry.vertexCount);\n texcoordAttr.init(geometry.vertexCount);\n var quadToTriangle = [0, 3, 1, 1, 3, 2]; // 3----2\n // 0----1\n // Make sure pixels on 1---3 edge will not have channel 0.\n // And pixels on four edges have at least one channel 0.\n\n var quadBarycentric = [[1, 1, 0, 0], [0, 1, 0, 1], [1, 0, 0, 1], [1, 0, 1, 0]];\n var indices = geometry.indices = new (geometry.vertexCount > 0xffff ? Uint32Array : Uint16Array)((row - 1) * (column - 1) * 6);\n\n var getQuadIndices = function (i, j, out) {\n out[1] = i * column + j;\n out[0] = i * column + j + 1;\n out[3] = (i + 1) * column + j + 1;\n out[2] = (i + 1) * column + j;\n };\n\n var isTransparent = false;\n\n if (needsSplitQuad) {\n var quadIndices = [];\n var pos = [];\n var faceOffset = 0;\n\n if (needsNormal) {\n normalAttr.init(geometry.vertexCount);\n } else {\n normalAttr.value = null;\n }\n\n var pts = [[], [], []];\n var v21 = [],\n v32 = [];\n var normal = vec3.create();\n\n var getFromArray = function (arr, idx, out) {\n var idx3 = idx * 3;\n out[0] = arr[idx3];\n out[1] = arr[idx3 + 1];\n out[2] = arr[idx3 + 2];\n return out;\n };\n\n var vertexNormals = new Float32Array(pointsArr.length);\n var vertexColors = new Float32Array(pointsArr.length / 3 * 4);\n\n for (var i = 0; i < data.count(); i++) {\n if (data.hasValue(i)) {\n var rgbaArr = graphicGL.parseColor(getItemVisualColor(data, i));\n var opacity = getItemVisualOpacity(data, i);\n opacity != null && (rgbaArr[3] *= opacity);\n\n if (rgbaArr[3] < 0.99) {\n isTransparent = true;\n }\n\n for (var k = 0; k < 4; k++) {\n vertexColors[i * 4 + k] = rgbaArr[k];\n }\n }\n }\n\n var farPoints = [1e7, 1e7, 1e7];\n\n for (var i = 0; i < row - 1; i++) {\n for (var j = 0; j < column - 1; j++) {\n var dataIndex = i * (column - 1) + j;\n var vertexOffset = dataIndex * 4;\n getQuadIndices(i, j, quadIndices);\n var invisibleQuad = false;\n\n for (var k = 0; k < 4; k++) {\n getFromArray(pointsArr, quadIndices[k], pos);\n\n if (isPointsNaN(pos)) {\n // Quad is invisible if any point is NaN\n invisibleQuad = true;\n }\n }\n\n for (var k = 0; k < 4; k++) {\n if (invisibleQuad) {\n // Move point far away\n positionAttr.set(vertexOffset + k, farPoints);\n } else {\n getFromArray(pointsArr, quadIndices[k], pos);\n positionAttr.set(vertexOffset + k, pos);\n }\n\n if (showWireframe) {\n barycentricAttr.set(vertexOffset + k, quadBarycentric[k]);\n }\n }\n\n for (var k = 0; k < 6; k++) {\n indices[faceOffset++] = quadToTriangle[k] + vertexOffset;\n } // Vertex normals\n\n\n if (needsNormal && !invisibleQuad) {\n for (var k = 0; k < 2; k++) {\n var k3 = k * 3;\n\n for (var m = 0; m < 3; m++) {\n var idx = quadIndices[quadToTriangle[k3] + m];\n getFromArray(pointsArr, idx, pts[m]);\n }\n\n vec3.sub(v21, pts[0], pts[1]);\n vec3.sub(v32, pts[1], pts[2]);\n vec3.cross(normal, v21, v32); // Weighted by the triangle area\n\n for (var m = 0; m < 3; m++) {\n var idx3 = quadIndices[quadToTriangle[k3] + m] * 3;\n vertexNormals[idx3] = vertexNormals[idx3] + normal[0];\n vertexNormals[idx3 + 1] = vertexNormals[idx3 + 1] + normal[1];\n vertexNormals[idx3 + 2] = vertexNormals[idx3 + 2] + normal[2];\n }\n }\n }\n }\n }\n\n if (needsNormal) {\n for (var i = 0; i < vertexNormals.length / 3; i++) {\n getFromArray(vertexNormals, i, normal);\n vec3.normalize(normal, normal);\n vertexNormals[i * 3] = normal[0];\n vertexNormals[i * 3 + 1] = normal[1];\n vertexNormals[i * 3 + 2] = normal[2];\n }\n } // Split normal and colors, write to the attributes.\n\n\n var rgbaArr = [];\n var uvArr = [];\n\n for (var i = 0; i < row - 1; i++) {\n for (var j = 0; j < column - 1; j++) {\n var dataIndex = i * (column - 1) + j;\n var vertexOffset = dataIndex * 4;\n getQuadIndices(i, j, quadIndices);\n\n for (var k = 0; k < 4; k++) {\n for (var m = 0; m < 4; m++) {\n rgbaArr[m] = vertexColors[quadIndices[k] * 4 + m];\n }\n\n colorAttr.set(vertexOffset + k, rgbaArr);\n\n if (needsNormal) {\n getFromArray(vertexNormals, quadIndices[k], normal);\n normalAttr.set(vertexOffset + k, normal);\n }\n\n var idx = quadIndices[k];\n uvArr[0] = idx % column / (column - 1);\n uvArr[1] = Math.floor(idx / column) / (row - 1);\n texcoordAttr.set(vertexOffset + k, uvArr);\n }\n\n dataIndex++;\n }\n }\n } else {\n var uvArr = [];\n\n for (var i = 0; i < data.count(); i++) {\n uvArr[0] = i % column / (column - 1);\n uvArr[1] = Math.floor(i / column) / (row - 1);\n var rgbaArr = graphicGL.parseColor(getItemVisualColor(data, i));\n var opacity = getItemVisualOpacity(data, i);\n opacity != null && (rgbaArr[3] *= opacity);\n\n if (rgbaArr[3] < 0.99) {\n isTransparent = true;\n }\n\n colorAttr.set(i, rgbaArr);\n texcoordAttr.set(i, uvArr);\n }\n\n var quadIndices = []; // Triangles\n\n var cursor = 0;\n\n for (var i = 0; i < row - 1; i++) {\n for (var j = 0; j < column - 1; j++) {\n getQuadIndices(i, j, quadIndices);\n\n for (var k = 0; k < 6; k++) {\n indices[cursor++] = quadIndices[quadToTriangle[k]];\n }\n }\n }\n\n if (needsNormal) {\n geometry.generateVertexNormals();\n } else {\n normalAttr.value = null;\n }\n }\n\n if (surfaceMesh.material.get('normalMap')) {\n geometry.generateTangents();\n }\n\n geometry.updateBoundingBox();\n geometry.dirty();\n surfaceMesh.material.transparent = isTransparent;\n surfaceMesh.material.depthMask = !isTransparent;\n },\n _getDataShape: function (data, isParametric) {\n var prevX = -Infinity;\n var rowCount = 0;\n var columnCount = 0;\n var prevColumnCount = 0;\n var mayInvalid = false;\n var rowDim = isParametric ? 'u' : 'x';\n var dataCount = data.count(); // Check data format\n\n for (var i = 0; i < dataCount; i++) {\n var x = data.get(rowDim, i);\n\n if (x < prevX) {\n if (prevColumnCount && prevColumnCount !== columnCount) {\n if (process.env.NODE_ENV !== 'production') {\n mayInvalid = true;\n }\n } // A new row.\n\n\n prevColumnCount = columnCount;\n columnCount = 0;\n rowCount++;\n }\n\n prevX = x;\n columnCount++;\n }\n\n if (!rowCount || columnCount === 1) {\n mayInvalid = true;\n }\n\n if (!mayInvalid) {\n return [rowCount + 1, columnCount];\n }\n\n var rows = Math.floor(Math.sqrt(dataCount));\n\n while (rows > 0) {\n if (Math.floor(dataCount / rows) === dataCount / rows) {\n // Can be divided\n return [rows, dataCount / rows];\n }\n\n rows--;\n } // Bailout\n\n\n rows = Math.floor(Math.sqrt(dataCount));\n return [rows, rows];\n },\n dispose: function () {\n this.groupGL.removeAll();\n },\n remove: function () {\n this.groupGL.removeAll();\n }\n});","// TODO ECharts GL must be imported whatever component,charts is imported.\nimport '../../echarts-gl';\nimport SurfaceSeries from './SurfaceSeries';\nimport SurfaceView from './SurfaceView';\nexport function install(registers) {\n registers.registerChartView(SurfaceView);\n registers.registerSeriesModel(SurfaceSeries);\n registers.registerLayout(function (ecModel, api) {\n ecModel.eachSeriesByType('surface', function (surfaceModel) {\n var cartesian = surfaceModel.coordinateSystem;\n\n if (!cartesian || cartesian.type !== 'cartesian3D') {\n if (process.env.NODE_ENV !== 'production') {\n console.error('Surface chart only support cartesian3D coordinateSystem');\n }\n }\n\n var data = surfaceModel.getData();\n var points = new Float32Array(3 * data.count());\n var nanPoint = [NaN, NaN, NaN];\n\n if (cartesian && cartesian.type === 'cartesian3D') {\n var coordDims = cartesian.dimensions;\n var dims = coordDims.map(function (coordDim) {\n return surfaceModel.coordDimToDataDim(coordDim)[0];\n });\n data.each(dims, function (x, y, z, idx) {\n var pt;\n\n if (!data.hasValue(idx)) {\n pt = nanPoint;\n } else {\n pt = cartesian.dataToPoint([x, y, z]);\n }\n\n points[idx * 3] = pt[0];\n points[idx * 3 + 1] = pt[1];\n points[idx * 3 + 2] = pt[2];\n });\n }\n\n data.setLayout('points', points);\n });\n });\n}","import * as echarts from 'echarts/lib/echarts';\nimport componentViewControlMixin from '../../component/common/componentViewControlMixin';\nimport componentPostEffectMixin from '../../component/common/componentPostEffectMixin';\nimport componentLightMixin from '../../component/common/componentLightMixin';\nimport componentShadingMixin from '../../component/common/componentShadingMixin';\nimport geo3DModelMixin from '../../coord/geo3D/geo3DModelMixin';\nimport formatUtil from '../../util/format';\nimport formatTooltip from '../common/formatTooltip';\nimport geo3DCreator from '../../coord/geo3DCreator';\n\nfunction transformPolygon(mapbox3DCoordSys, poly) {\n var newPoly = [];\n\n for (var k = 0; k < poly.length; k++) {\n newPoly.push(mapbox3DCoordSys.dataToPoint(poly[k]));\n }\n\n return newPoly;\n}\n\nvar Map3DSeries = echarts.SeriesModel.extend({\n type: 'series.map3D',\n layoutMode: 'box',\n coordinateSystem: null,\n visualStyleAccessPath: 'itemStyle',\n optionUpdated: function (newOpt) {\n newOpt = newOpt || {};\n var coordSysType = this.get('coordinateSystem');\n\n if (coordSysType == null || coordSysType === 'geo3D') {\n return;\n }\n\n if (process.env.NODE_ENV !== 'production') {\n var propsNeedToCheck = ['left', 'top', 'width', 'height', 'boxWidth', 'boxDepth', 'boxHeight', 'light', 'viewControl', 'postEffect', 'temporalSuperSampling', 'environment', 'groundPlane'];\n var ignoredProperties = [];\n propsNeedToCheck.forEach(function (propName) {\n if (newOpt[propName] != null) {\n ignoredProperties.push(propName);\n }\n });\n\n if (ignoredProperties.length) {\n console.warn('Property %s in map3D series will be ignored if coordinate system is %s', ignoredProperties.join(', '), coordSysType);\n }\n }\n\n if (this.get('groundPlane.show')) {\n // Force disable groundPlane if map3D has other coordinate systems.\n this.option.groundPlane.show = false;\n } // Reset geo.\n\n\n this._geo = null;\n },\n getInitialData: function (option) {\n option.data = this.getFilledRegions(option.data, option.map);\n var dimensions = echarts.helper.createDimensions(option.data, {\n coordDimensions: ['value']\n });\n var list = new echarts.List(dimensions, this);\n list.initData(option.data);\n var regionModelMap = {};\n list.each(function (idx) {\n var name = list.getName(idx);\n var itemModel = list.getItemModel(idx);\n regionModelMap[name] = itemModel;\n });\n this._regionModelMap = regionModelMap;\n return list;\n },\n formatTooltip: function (dataIndex) {\n return formatTooltip(this, dataIndex);\n },\n getRegionModel: function (idx) {\n var name = this.getData().getName(idx);\n return this._regionModelMap[name] || new echarts.Model(null, this);\n },\n getRegionPolygonCoords: function (idx) {\n var coordSys = this.coordinateSystem;\n var name = this.getData().getName(idx);\n\n if (coordSys.transform) {\n var region = coordSys.getRegion(name);\n return region ? region.geometries : [];\n } else {\n if (!this._geo) {\n this._geo = geo3DCreator.createGeo3D(this);\n }\n\n var region = this._geo.getRegion(name);\n\n var ret = [];\n\n for (var k = 0; k < region.geometries.length; k++) {\n var geo = region.geometries[k];\n var interiors = [];\n var exterior = transformPolygon(coordSys, geo.exterior);\n\n if (interiors && interiors.length) {\n for (var m = 0; m < geo.interiors.length; m++) {\n interiors.push(transformPolygon(coordSys, interiors[m]));\n }\n }\n\n ret.push({\n interiors: interiors,\n exterior: exterior\n });\n }\n\n return ret;\n }\n },\n\n /**\n * Format label\n * @param {string} name Region name\n * @param {string} [status='normal'] 'normal' or 'emphasis'\n * @return {string}\n */\n getFormattedLabel: function (dataIndex, status) {\n var text = formatUtil.getFormattedLabel(this, dataIndex, status);\n\n if (text == null) {\n text = this.getData().getName(dataIndex);\n }\n\n return text;\n },\n defaultOption: {\n // Support geo3D, mapbox, maptalks3D\n coordinateSystem: 'geo3D',\n // itemStyle: {},\n // height,\n // label: {}\n data: null\n }\n});\necharts.util.merge(Map3DSeries.prototype, geo3DModelMixin);\necharts.util.merge(Map3DSeries.prototype, componentViewControlMixin);\necharts.util.merge(Map3DSeries.prototype, componentPostEffectMixin);\necharts.util.merge(Map3DSeries.prototype, componentLightMixin);\necharts.util.merge(Map3DSeries.prototype, componentShadingMixin);\nexport default Map3DSeries;","import { use } from 'echarts/lib/echarts';\nimport { install } from './surface/install';\nuse(install);","import * as echarts from 'echarts/lib/echarts';\nimport graphicGL from '../../util/graphicGL';\nimport OrbitControl from '../../util/OrbitControl';\nimport SceneHelper from '../../component/common/SceneHelper';\nimport Geo3DBuilder from '../../component/common/Geo3DBuilder';\nexport default echarts.ChartView.extend({\n type: 'map3D',\n __ecgl__: true,\n init: function (ecModel, api) {\n this._geo3DBuilder = new Geo3DBuilder(api);\n this.groupGL = new graphicGL.Node();\n },\n render: function (map3DModel, ecModel, api) {\n var coordSys = map3DModel.coordinateSystem;\n\n if (!coordSys || !coordSys.viewGL) {\n return;\n }\n\n this.groupGL.add(this._geo3DBuilder.rootNode);\n coordSys.viewGL.add(this.groupGL);\n var geo3D;\n\n if (coordSys.type === 'geo3D') {\n geo3D = coordSys;\n\n if (!this._sceneHelper) {\n this._sceneHelper = new SceneHelper();\n\n this._sceneHelper.initLight(this.groupGL);\n }\n\n this._sceneHelper.setScene(coordSys.viewGL.scene);\n\n this._sceneHelper.updateLight(map3DModel); // Set post effect\n\n\n coordSys.viewGL.setPostEffect(map3DModel.getModel('postEffect'), api);\n coordSys.viewGL.setTemporalSuperSampling(map3DModel.getModel('temporalSuperSampling'));\n var control = this._control;\n\n if (!control) {\n control = this._control = new OrbitControl({\n zr: api.getZr()\n });\n\n this._control.init();\n }\n\n var viewControlModel = map3DModel.getModel('viewControl');\n control.setViewGL(coordSys.viewGL);\n control.setFromViewControlModel(viewControlModel, 0);\n control.off('update');\n control.on('update', function () {\n api.dispatchAction({\n type: 'map3DChangeCamera',\n alpha: control.getAlpha(),\n beta: control.getBeta(),\n distance: control.getDistance(),\n from: this.uid,\n map3DId: map3DModel.id\n });\n });\n this._geo3DBuilder.extrudeY = true;\n } else {\n if (this._control) {\n this._control.dispose();\n\n this._control = null;\n }\n\n if (this._sceneHelper) {\n this._sceneHelper.dispose();\n\n this._sceneHelper = null;\n }\n\n geo3D = map3DModel.getData().getLayout('geo3D');\n this._geo3DBuilder.extrudeY = false;\n }\n\n this._geo3DBuilder.update(map3DModel, ecModel, api, 0, map3DModel.getData().count()); // Must update after geo3D.viewGL.setPostEffect to determine linear space\n\n\n var srgbDefineMethod = coordSys.viewGL.isLinearSpace() ? 'define' : 'undefine';\n\n this._geo3DBuilder.rootNode.traverse(function (mesh) {\n if (mesh.material) {\n mesh.material[srgbDefineMethod]('fragment', 'SRGB_DECODE');\n }\n });\n },\n afterRender: function (map3DModel, ecModel, api, layerGL) {\n var renderer = layerGL.renderer;\n var coordSys = map3DModel.coordinateSystem;\n\n if (coordSys && coordSys.type === 'geo3D') {\n this._sceneHelper.updateAmbientCubemap(renderer, map3DModel, api);\n\n this._sceneHelper.updateSkybox(renderer, map3DModel, api);\n }\n },\n dispose: function () {\n this.groupGL.removeAll();\n\n this._control.dispose();\n\n this._geo3DBuilder.dispose();\n }\n});","// TODO ECharts GL must be imported whatever component,charts is imported.\nimport '../../echarts-gl';\nimport Map3DSeries from './Map3DSeries';\nimport Map3DView from './Map3DView';\nimport { install as installGeo3D } from '../../component/geo3D/install';\nexport function install(registers) {\n // Depends on geo3d\n installGeo3D(registers);\n registers.registerChartView(Map3DView);\n registers.registerSeriesModel(Map3DSeries);\n registers.registerAction({\n type: 'map3DChangeCamera',\n event: 'map3dcamerachanged',\n update: 'series:updateCamera'\n }, function (payload, ecModel) {\n ecModel.eachComponent({\n mainType: 'series',\n subType: 'map3D',\n query: payload\n }, function (componentModel) {\n componentModel.setView(payload);\n });\n });\n}","import { use } from 'echarts/lib/echarts';\nimport { install } from './map3D/install';\nuse(install);","import * as echarts from 'echarts/lib/echarts';\nexport default echarts.SeriesModel.extend({\n type: 'series.scatterGL',\n dependencies: ['grid', 'polar', 'geo', 'singleAxis'],\n visualStyleAccessPath: 'itemStyle',\n hasSymbolVisual: true,\n getInitialData: function () {\n return echarts.helper.createList(this);\n },\n defaultOption: {\n coordinateSystem: 'cartesian2d',\n zlevel: 10,\n progressive: 1e5,\n progressiveThreshold: 1e5,\n // Cartesian coordinate system\n // xAxisIndex: 0,\n // yAxisIndex: 0,\n // Polar coordinate system\n // polarIndex: 0,\n // Geo coordinate system\n // geoIndex: 0,\n large: false,\n symbol: 'circle',\n symbolSize: 10,\n // symbolSize scale when zooming.\n zoomScale: 0,\n // Support source-over, lighter\n blendMode: 'source-over',\n itemStyle: {\n opacity: 0.8\n },\n postEffect: {\n enable: false,\n colorCorrection: {\n exposure: 0,\n brightness: 0,\n contrast: 1,\n saturation: 1,\n enable: true\n }\n }\n }\n});","import * as matrix from 'zrender/lib/core/matrix';\nimport * as vector from 'zrender/lib/core/vector';\n\nfunction GLViewHelper(viewGL) {\n this.viewGL = viewGL;\n}\n\nGLViewHelper.prototype.reset = function (seriesModel, api) {\n this._updateCamera(api.getWidth(), api.getHeight(), api.getDevicePixelRatio());\n\n this._viewTransform = matrix.create();\n this.updateTransform(seriesModel, api);\n};\n\nGLViewHelper.prototype.updateTransform = function (seriesModel, api) {\n var coordinateSystem = seriesModel.coordinateSystem;\n\n if (coordinateSystem.getRoamTransform) {\n matrix.invert(this._viewTransform, coordinateSystem.getRoamTransform());\n\n this._setCameraTransform(this._viewTransform);\n\n api.getZr().refresh();\n }\n}; // Reimplement the dataToPoint of coordinate system.\n// Remove the effect of pan/zoom transform\n\n\nGLViewHelper.prototype.dataToPoint = function (coordSys, data, pt) {\n pt = coordSys.dataToPoint(data, null, pt);\n var viewTransform = this._viewTransform;\n\n if (viewTransform) {\n vector.applyTransform(pt, pt, viewTransform);\n }\n};\n/**\n * Remove transform info in point.\n */\n\n\nGLViewHelper.prototype.removeTransformInPoint = function (pt) {\n if (this._viewTransform) {\n vector.applyTransform(pt, pt, this._viewTransform);\n }\n\n return pt;\n};\n/**\n * Return number\n */\n\n\nGLViewHelper.prototype.getZoom = function () {\n if (this._viewTransform) {\n var m = this._viewTransform;\n return 1 / Math.max(Math.sqrt(m[0] * m[0] + m[1] * m[1]), Math.sqrt(m[2] * m[2] + m[3] * m[3]));\n }\n\n return 1;\n};\n\nGLViewHelper.prototype._setCameraTransform = function (m) {\n var camera = this.viewGL.camera;\n camera.position.set(m[4], m[5], 0);\n camera.scale.set(Math.sqrt(m[0] * m[0] + m[1] * m[1]), Math.sqrt(m[2] * m[2] + m[3] * m[3]), 1);\n};\n\nGLViewHelper.prototype._updateCamera = function (width, height, dpr) {\n // TODO, left, top, right, bottom\n this.viewGL.setViewport(0, 0, width, height, dpr);\n var camera = this.viewGL.camera;\n camera.left = camera.top = 0;\n camera.bottom = height;\n camera.right = width;\n camera.near = 0;\n camera.far = 100;\n};\n\nexport default GLViewHelper;","import * as echarts from 'echarts/lib/echarts';\nimport graphicGL from '../../util/graphicGL';\nimport ViewGL from '../../core/ViewGL';\nimport PointsBuilder from '../common/PointsBuilder';\nimport GLViewHelper from '../common/GLViewHelper';\nexport default echarts.ChartView.extend({\n type: 'scatterGL',\n __ecgl__: true,\n init: function (ecModel, api) {\n this.groupGL = new graphicGL.Node();\n this.viewGL = new ViewGL('orthographic');\n this.viewGL.add(this.groupGL);\n this._pointsBuilderList = [];\n this._currentStep = 0;\n this._sizeScale = 1;\n this._glViewHelper = new GLViewHelper(this.viewGL);\n },\n render: function (seriesModel, ecModel, api) {\n this.groupGL.removeAll();\n\n this._glViewHelper.reset(seriesModel, api);\n\n if (!seriesModel.getData().count()) {\n return;\n }\n\n var pointsBuilder = this._pointsBuilderList[0];\n\n if (!pointsBuilder) {\n pointsBuilder = this._pointsBuilderList[0] = new PointsBuilder(true, api);\n }\n\n this._pointsBuilderList.length = 1;\n this.groupGL.add(pointsBuilder.rootNode);\n\n this._removeTransformInPoints(seriesModel.getData().getLayout('points'));\n\n pointsBuilder.update(seriesModel, ecModel, api);\n this.viewGL.setPostEffect(seriesModel.getModel('postEffect'), api);\n },\n incrementalPrepareRender: function (seriesModel, ecModel, api) {\n this.groupGL.removeAll();\n\n this._glViewHelper.reset(seriesModel, api);\n\n this._currentStep = 0;\n this.viewGL.setPostEffect(seriesModel.getModel('postEffect'), api);\n },\n incrementalRender: function (params, seriesModel, ecModel, api) {\n if (params.end <= params.start) {\n return;\n }\n\n var pointsBuilder = this._pointsBuilderList[this._currentStep];\n\n if (!pointsBuilder) {\n pointsBuilder = new PointsBuilder(true, api);\n this._pointsBuilderList[this._currentStep] = pointsBuilder;\n }\n\n this.groupGL.add(pointsBuilder.rootNode);\n\n this._removeTransformInPoints(seriesModel.getData().getLayout('points'));\n\n pointsBuilder.setSizeScale(this._sizeScale);\n pointsBuilder.update(seriesModel, ecModel, api, params.start, params.end);\n api.getZr().refresh();\n this._currentStep++;\n },\n updateTransform: function (seriesModel, ecModel, api) {\n if (seriesModel.coordinateSystem.getRoamTransform) {\n this._glViewHelper.updateTransform(seriesModel, api);\n\n var zoom = this._glViewHelper.getZoom();\n\n var sizeScale = Math.max((seriesModel.get('zoomScale') || 0) * (zoom - 1) + 1, 0);\n this._sizeScale = sizeScale;\n\n this._pointsBuilderList.forEach(function (pointsBuilder) {\n pointsBuilder.setSizeScale(sizeScale);\n });\n }\n },\n _removeTransformInPoints: function (points) {\n if (!points) {\n return;\n }\n\n var pt = [];\n\n for (var i = 0; i < points.length; i += 2) {\n pt[0] = points[i];\n pt[1] = points[i + 1];\n\n this._glViewHelper.removeTransformInPoint(pt);\n\n points[i] = pt[0];\n points[i + 1] = pt[1];\n }\n },\n dispose: function () {\n this.groupGL.removeAll();\n\n this._pointsBuilderList.forEach(function (pointsBuilder) {\n pointsBuilder.dispose();\n });\n },\n remove: function () {\n this.groupGL.removeAll();\n }\n});","// TODO ECharts GL must be imported whatever component,charts is imported.\nimport '../../echarts-gl';\nimport ScatterGLSeries from './ScatterGLSeries';\nimport ScatterGLView from './ScatterGLView';\nexport function install(registers) {\n registers.registerChartView(ScatterGLView);\n registers.registerSeriesModel(ScatterGLSeries);\n registers.registerLayout({\n seriesType: 'scatterGL',\n reset: function (seriesModel) {\n var coordSys = seriesModel.coordinateSystem;\n var data = seriesModel.getData();\n var progress;\n\n if (coordSys) {\n var dims = coordSys.dimensions.map(function (dim) {\n return data.mapDimension(dim);\n }).slice(0, 2);\n var pt = [];\n\n if (dims.length === 1) {\n progress = function (params) {\n var points = new Float32Array((params.end - params.start) * 2);\n\n for (var idx = params.start; idx < params.end; idx++) {\n var offset = (idx - params.start) * 2;\n var x = data.get(dims[0], idx);\n var pt = coordSys.dataToPoint(x);\n points[offset] = pt[0];\n points[offset + 1] = pt[1];\n }\n\n data.setLayout('points', points);\n };\n } else if (dims.length === 2) {\n progress = function (params) {\n var points = new Float32Array((params.end - params.start) * 2);\n\n for (var idx = params.start; idx < params.end; idx++) {\n var offset = (idx - params.start) * 2;\n var x = data.get(dims[0], idx);\n var y = data.get(dims[1], idx);\n pt[0] = x;\n pt[1] = y;\n pt = coordSys.dataToPoint(pt);\n points[offset] = pt[0];\n points[offset + 1] = pt[1];\n }\n\n data.setLayout('points', points);\n };\n }\n }\n\n return {\n progress: progress\n };\n }\n });\n}","import { use } from 'echarts/lib/echarts';\nimport { install } from './scatterGL/install';\nuse(install);","\n/*\n* Licensed to the Apache Software Foundation (ASF) under one\n* or more contributor license agreements. See the NOTICE file\n* distributed with this work for additional information\n* regarding copyright ownership. The ASF licenses this file\n* to you under the Apache License, Version 2.0 (the\n* \"License\"); you may not use this file except in compliance\n* with the License. You may obtain a copy of the License at\n*\n* http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing,\n* software distributed under the License is distributed on an\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n* KIND, either express or implied. See the License for the\n* specific language governing permissions and limitations\n* under the License.\n*/\n\n\n/**\n * AUTO-GENERATED FILE. DO NOT MODIFY.\n */\n\n/*\r\n* Licensed to the Apache Software Foundation (ASF) under one\r\n* or more contributor license agreements. See the NOTICE file\r\n* distributed with this work for additional information\r\n* regarding copyright ownership. The ASF licenses this file\r\n* to you under the Apache License, Version 2.0 (the\r\n* \"License\"); you may not use this file except in compliance\r\n* with the License. You may obtain a copy of the License at\r\n*\r\n* http://www.apache.org/licenses/LICENSE-2.0\r\n*\r\n* Unless required by applicable law or agreed to in writing,\r\n* software distributed under the License is distributed on an\r\n* \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\r\n* KIND, either express or implied. See the License for the\r\n* specific language governing permissions and limitations\r\n* under the License.\r\n*/\n// TODO: this module is only for compatibility with echarts-gl\nimport linkSeriesData from './linkSeriesData.js';\nexport default linkSeriesData;","import * as echarts from 'echarts/lib/echarts';\nimport Graph from 'echarts/lib/data/Graph';\nimport linkList from 'echarts/lib/data/helper/linkList';\nimport retrieve from '../../util/retrieve';\nexport default function (nodes, edges, hostModel, directed, beforeLink) {\n var graph = new Graph(directed);\n\n for (var i = 0; i < nodes.length; i++) {\n graph.addNode(retrieve.firstNotNull( // Id, name, dataIndex\n nodes[i].id, nodes[i].name, i), i);\n }\n\n var linkNameList = [];\n var validEdges = [];\n var linkCount = 0;\n\n for (var i = 0; i < edges.length; i++) {\n var link = edges[i];\n var source = link.source;\n var target = link.target; // addEdge may fail when source or target not exists\n\n if (graph.addEdge(source, target, linkCount)) {\n validEdges.push(link);\n linkNameList.push(retrieve.firstNotNull(link.id, source + ' > ' + target));\n linkCount++;\n }\n }\n\n var nodeData; // FIXME, support more coordinate systems.\n\n var dimensionNames = echarts.helper.createDimensions(nodes, {\n coordDimensions: ['value']\n });\n nodeData = new echarts.List(dimensionNames, hostModel);\n nodeData.initData(nodes);\n var edgeData = new echarts.List(['value'], hostModel);\n edgeData.initData(validEdges, linkNameList);\n beforeLink && beforeLink(nodeData, edgeData);\n linkList({\n mainData: nodeData,\n struct: graph,\n structAttr: 'graph',\n datas: {\n node: nodeData,\n edge: edgeData\n },\n datasAttr: {\n node: 'data',\n edge: 'edgeData'\n }\n }); // Update dataIndex of nodes and edges because invalid edge may be removed\n\n graph.update();\n return graph;\n}\n;","import * as echarts from 'echarts/lib/echarts';\nimport createGraphFromNodeEdge from './createGraphFromNodeEdge';\nimport formatUtil from '../../util/format';\nvar GraphSeries = echarts.SeriesModel.extend({\n type: 'series.graphGL',\n visualStyleAccessPath: 'itemStyle',\n hasSymbolVisual: true,\n init: function (option) {\n GraphSeries.superApply(this, 'init', arguments); // Provide data for legend select\n\n this.legendDataProvider = function () {\n return this._categoriesData;\n };\n\n this._updateCategoriesData();\n },\n mergeOption: function (option) {\n GraphSeries.superApply(this, 'mergeOption', arguments);\n\n this._updateCategoriesData();\n },\n getFormattedLabel: function (dataIndex, status, dataType, dimIndex) {\n var text = formatUtil.getFormattedLabel(this, dataIndex, status, dataType, dimIndex);\n\n if (text == null) {\n var data = this.getData();\n var lastDim = data.dimensions[data.dimensions.length - 1];\n text = data.get(lastDim, dataIndex);\n }\n\n return text;\n },\n getInitialData: function (option, ecModel) {\n var edges = option.edges || option.links || [];\n var nodes = option.data || option.nodes || [];\n var self = this;\n\n if (nodes && edges) {\n return createGraphFromNodeEdge(nodes, edges, this, true, beforeLink).data;\n }\n\n function beforeLink(nodeData, edgeData) {\n // Overwrite nodeData.getItemModel to\n nodeData.wrapMethod('getItemModel', function (model) {\n const categoriesModels = self._categoriesModels;\n const categoryIdx = model.getShallow('category');\n const categoryModel = categoriesModels[categoryIdx];\n\n if (categoryModel) {\n categoryModel.parentModel = model.parentModel;\n model.parentModel = categoryModel;\n }\n\n return model;\n }); // TODO Inherit resolveParentPath by default in Model#getModel?\n\n const oldGetModel = ecModel.getModel([]).getModel;\n\n function newGetModel(path, parentModel) {\n const model = oldGetModel.call(this, path, parentModel);\n model.resolveParentPath = resolveParentPath;\n return model;\n }\n\n edgeData.wrapMethod('getItemModel', function (model) {\n model.resolveParentPath = resolveParentPath;\n model.getModel = newGetModel;\n return model;\n });\n\n function resolveParentPath(pathArr) {\n if (pathArr && (pathArr[0] === 'label' || pathArr[1] === 'label')) {\n const newPathArr = pathArr.slice();\n\n if (pathArr[0] === 'label') {\n newPathArr[0] = 'edgeLabel';\n } else if (pathArr[1] === 'label') {\n newPathArr[1] = 'edgeLabel';\n }\n\n return newPathArr;\n }\n\n return pathArr;\n }\n }\n },\n\n /**\n * @return {module:echarts/data/Graph}\n */\n getGraph: function () {\n return this.getData().graph;\n },\n\n /**\n * @return {module:echarts/data/List}\n */\n getEdgeData: function () {\n return this.getGraph().edgeData;\n },\n\n /**\n * @return {module:echarts/data/List}\n */\n getCategoriesData: function () {\n return this._categoriesData;\n },\n\n /**\n * @override\n */\n formatTooltip: function (dataIndex, multipleSeries, dataType) {\n if (dataType === 'edge') {\n var nodeData = this.getData();\n var params = this.getDataParams(dataIndex, dataType);\n var edge = nodeData.graph.getEdgeByIndex(dataIndex);\n var sourceName = nodeData.getName(edge.node1.dataIndex);\n var targetName = nodeData.getName(edge.node2.dataIndex);\n var html = [];\n sourceName != null && html.push(sourceName);\n targetName != null && html.push(targetName);\n html = echarts.format.encodeHTML(html.join(' > '));\n\n if (params.value) {\n html += ' : ' + echarts.format.encodeHTML(params.value);\n }\n\n return html;\n } else {\n // dataType === 'node' or empty\n return GraphSeries.superApply(this, 'formatTooltip', arguments);\n }\n },\n _updateCategoriesData: function () {\n var categories = (this.option.categories || []).map(function (category) {\n // Data must has value\n return category.value != null ? category : Object.assign({\n value: 0\n }, category);\n });\n var categoriesData = new echarts.List(['value'], this);\n categoriesData.initData(categories);\n this._categoriesData = categoriesData;\n this._categoriesModels = categoriesData.mapArray(function (idx) {\n return categoriesData.getItemModel(idx, true);\n });\n },\n setView: function (payload) {\n if (payload.zoom != null) {\n this.option.zoom = payload.zoom;\n }\n\n if (payload.offset != null) {\n this.option.offset = payload.offset;\n }\n },\n setNodePosition: function (points) {\n for (var i = 0; i < points.length / 2; i++) {\n var x = points[i * 2];\n var y = points[i * 2 + 1];\n var opt = this.getData().getRawDataItem(i);\n opt.x = x;\n opt.y = y;\n }\n },\n isAnimationEnabled: function () {\n return GraphSeries.superCall(this, 'isAnimationEnabled') // Not enable animation when do force layout\n && !(this.get('layout') === 'force' && this.get('force.layoutAnimation'));\n },\n defaultOption: {\n zlevel: 10,\n z: 2,\n legendHoverLink: true,\n // Only support forceAtlas2\n layout: 'forceAtlas2',\n // Configuration of force directed layout\n forceAtlas2: {\n initLayout: null,\n GPU: true,\n steps: 1,\n // barnesHutOptimize\n // Maxp layout steps.\n maxSteps: 1000,\n repulsionByDegree: true,\n linLogMode: false,\n strongGravityMode: false,\n gravity: 1.0,\n // scaling: 1.0,\n edgeWeightInfluence: 1.0,\n // Edge weight range.\n edgeWeight: [1, 4],\n // Node weight range.\n nodeWeight: [1, 4],\n // jitterTolerence: 0.1,\n preventOverlap: false,\n gravityCenter: null\n },\n focusNodeAdjacency: true,\n focusNodeAdjacencyOn: 'mouseover',\n left: 'center',\n top: 'center',\n // right: null,\n // bottom: null,\n // width: '80%',\n // height: '80%',\n symbol: 'circle',\n symbolSize: 5,\n roam: false,\n // Default on center of graph\n center: null,\n zoom: 1,\n // categories: [],\n // data: []\n // Or\n // nodes: []\n //\n // links: []\n // Or\n // edges: []\n label: {\n show: false,\n formatter: '{b}',\n position: 'right',\n distance: 5,\n textStyle: {\n fontSize: 14\n }\n },\n itemStyle: {},\n lineStyle: {\n color: '#aaa',\n width: 1,\n opacity: 0.5\n },\n emphasis: {\n label: {\n show: true\n }\n },\n animation: false\n }\n});\nexport default GraphSeries;","/**\n * Lines geometry\n * Use screen space projected lines lineWidth > MAX_LINE_WIDTH\n * https://mattdesl.svbtle.com/drawing-lines-is-hard\n * @module echarts-gl/util/geometry/LinesGeometry\n * @author Yi Shen(http://github.com/pissang)\n */\nimport Geometry from 'claygl/src/Geometry';\nimport * as echarts from 'echarts/lib/echarts';\nimport dynamicConvertMixin from './dynamicConvertMixin';\nimport glmatrix from 'claygl/src/dep/glmatrix';\nvar vec2 = glmatrix.vec2; // var CURVE_RECURSION_LIMIT = 8;\n// var CURVE_COLLINEAR_EPSILON = 40;\n\nvar sampleLinePoints = [[0, 0], [1, 1]];\n/**\n * @constructor\n * @alias module:echarts-gl/util/geometry/LinesGeometry\n * @extends clay.Geometry\n */\n\nvar LinesGeometry = Geometry.extend(function () {\n return {\n segmentScale: 4,\n dynamic: true,\n\n /**\n * Need to use mesh to expand lines if lineWidth > MAX_LINE_WIDTH\n */\n useNativeLine: true,\n attributes: {\n position: new Geometry.Attribute('position', 'float', 2, 'POSITION'),\n normal: new Geometry.Attribute('normal', 'float', 2),\n offset: new Geometry.Attribute('offset', 'float', 1),\n color: new Geometry.Attribute('color', 'float', 4, 'COLOR')\n }\n };\n},\n/** @lends module: echarts-gl/util/geometry/LinesGeometry.prototype */\n{\n /**\n * Reset offset\n */\n resetOffset: function () {\n this._vertexOffset = 0;\n this._faceOffset = 0;\n this._itemVertexOffsets = [];\n },\n\n /**\n * @param {number} nVertex\n */\n setVertexCount: function (nVertex) {\n var attributes = this.attributes;\n\n if (this.vertexCount !== nVertex) {\n attributes.position.init(nVertex);\n attributes.color.init(nVertex);\n\n if (!this.useNativeLine) {\n attributes.offset.init(nVertex);\n attributes.normal.init(nVertex);\n }\n\n if (nVertex > 0xffff) {\n if (this.indices instanceof Uint16Array) {\n this.indices = new Uint32Array(this.indices);\n }\n } else {\n if (this.indices instanceof Uint32Array) {\n this.indices = new Uint16Array(this.indices);\n }\n }\n }\n },\n\n /**\n * @param {number} nTriangle\n */\n setTriangleCount: function (nTriangle) {\n if (this.triangleCount !== nTriangle) {\n if (nTriangle === 0) {\n this.indices = null;\n } else {\n this.indices = this.vertexCount > 0xffff ? new Uint32Array(nTriangle * 3) : new Uint16Array(nTriangle * 3);\n }\n }\n },\n _getCubicCurveApproxStep: function (p0, p1, p2, p3) {\n var len = vec2.dist(p0, p1) + vec2.dist(p2, p1) + vec2.dist(p3, p2);\n var step = 1 / (len + 1) * this.segmentScale;\n return step;\n },\n\n /**\n * Get vertex count of cubic curve\n * @param {Array.} p0\n * @param {Array.} p1\n * @param {Array.} p2\n * @param {Array.} p3\n * @return number\n */\n getCubicCurveVertexCount: function (p0, p1, p2, p3) {\n var step = this._getCubicCurveApproxStep(p0, p1, p2, p3);\n\n var segCount = Math.ceil(1 / step);\n\n if (!this.useNativeLine) {\n return segCount * 2 + 2;\n } else {\n return segCount * 2;\n }\n },\n\n /**\n * Get face count of cubic curve\n * @param {Array.} p0\n * @param {Array.} p1\n * @param {Array.} p2\n * @param {Array.} p3\n * @return number\n */\n getCubicCurveTriangleCount: function (p0, p1, p2, p3) {\n var step = this._getCubicCurveApproxStep(p0, p1, p2, p3);\n\n var segCount = Math.ceil(1 / step);\n\n if (!this.useNativeLine) {\n return segCount * 2;\n } else {\n return 0;\n }\n },\n\n /**\n * Get vertex count of line\n * @return {number}\n */\n getLineVertexCount: function () {\n return this.getPolylineVertexCount(sampleLinePoints);\n },\n\n /**\n * Get face count of line\n * @return {number}\n */\n getLineTriangleCount: function () {\n return this.getPolylineTriangleCount(sampleLinePoints);\n },\n\n /**\n * Get how many vertices will polyline take.\n * @type {number|Array} points Can be a 1d/2d list of points, or a number of points amount.\n * @return {number}\n */\n getPolylineVertexCount: function (points) {\n var pointsLen;\n\n if (typeof points === 'number') {\n pointsLen = points;\n } else {\n var is2DArray = typeof points[0] !== 'number';\n pointsLen = is2DArray ? points.length : points.length / 2;\n }\n\n return !this.useNativeLine ? (pointsLen - 1) * 2 + 2 : (pointsLen - 1) * 2;\n },\n\n /**\n * Get how many triangles will polyline take.\n * @type {number|Array} points Can be a 1d/2d list of points, or a number of points amount.\n * @return {number}\n */\n getPolylineTriangleCount: function (points) {\n var pointsLen;\n\n if (typeof points === 'number') {\n pointsLen = points;\n } else {\n var is2DArray = typeof points[0] !== 'number';\n pointsLen = is2DArray ? points.length : points.length / 2;\n }\n\n return !this.useNativeLine ? (pointsLen - 1) * 2 : 0;\n },\n\n /**\n * Add a cubic curve\n * @param {Array.} p0\n * @param {Array.} p1\n * @param {Array.} p2\n * @param {Array.} p3\n * @param {Array.} color\n * @param {number} [lineWidth=1]\n */\n addCubicCurve: function (p0, p1, p2, p3, color, lineWidth) {\n if (lineWidth == null) {\n lineWidth = 1;\n } // incremental interpolation\n // http://antigrain.com/research/bezier_interpolation/index.html#PAGE_BEZIER_INTERPOLATION\n\n\n var x0 = p0[0],\n y0 = p0[1];\n var x1 = p1[0],\n y1 = p1[1];\n var x2 = p2[0],\n y2 = p2[1];\n var x3 = p3[0],\n y3 = p3[1];\n\n var step = this._getCubicCurveApproxStep(p0, p1, p2, p3);\n\n var step2 = step * step;\n var step3 = step2 * step;\n var pre1 = 3.0 * step;\n var pre2 = 3.0 * step2;\n var pre4 = 6.0 * step2;\n var pre5 = 6.0 * step3;\n var tmp1x = x0 - x1 * 2.0 + x2;\n var tmp1y = y0 - y1 * 2.0 + y2;\n var tmp2x = (x1 - x2) * 3.0 - x0 + x3;\n var tmp2y = (y1 - y2) * 3.0 - y0 + y3;\n var fx = x0;\n var fy = y0;\n var dfx = (x1 - x0) * pre1 + tmp1x * pre2 + tmp2x * step3;\n var dfy = (y1 - y0) * pre1 + tmp1y * pre2 + tmp2y * step3;\n var ddfx = tmp1x * pre4 + tmp2x * pre5;\n var ddfy = tmp1y * pre4 + tmp2y * pre5;\n var dddfx = tmp2x * pre5;\n var dddfy = tmp2y * pre5;\n var t = 0;\n var k = 0;\n var segCount = Math.ceil(1 / step);\n var points = new Float32Array((segCount + 1) * 3);\n var points = [];\n var offset = 0;\n\n for (var k = 0; k < segCount + 1; k++) {\n points[offset++] = fx;\n points[offset++] = fy;\n fx += dfx;\n fy += dfy;\n dfx += ddfx;\n dfy += ddfy;\n ddfx += dddfx;\n ddfy += dddfy;\n t += step;\n\n if (t > 1) {\n fx = dfx > 0 ? Math.min(fx, x3) : Math.max(fx, x3);\n fy = dfy > 0 ? Math.min(fy, y3) : Math.max(fy, y3);\n }\n }\n\n this.addPolyline(points, color, lineWidth);\n },\n\n /**\n * Add a straight line\n * @param {Array.} p0\n * @param {Array.} p1\n * @param {Array.} color\n * @param {number} [lineWidth=1]\n */\n addLine: function (p0, p1, color, lineWidth) {\n this.addPolyline([p0, p1], color, lineWidth);\n },\n\n /**\n * Add a straight line\n * @param {Array. | Array.} points\n * @param {Array. | Array.} color\n * @param {number} [lineWidth=1]\n * @param {number} [arrayOffset=0]\n * @param {number} [pointsCount] Default to be amount of points in the first argument\n */\n addPolyline: function () {\n var dirA = vec2.create();\n var dirB = vec2.create();\n var normal = vec2.create();\n var tangent = vec2.create();\n var point = [],\n nextPoint = [],\n prevPoint = [];\n return function (points, color, lineWidth, arrayOffset, pointsCount) {\n if (!points.length) {\n return;\n }\n\n var is2DArray = typeof points[0] !== 'number';\n\n if (pointsCount == null) {\n pointsCount = is2DArray ? points.length : points.length / 2;\n }\n\n if (pointsCount < 2) {\n return;\n }\n\n if (arrayOffset == null) {\n arrayOffset = 0;\n }\n\n if (lineWidth == null) {\n lineWidth = 1;\n }\n\n this._itemVertexOffsets.push(this._vertexOffset);\n\n var notSharingColor = is2DArray ? typeof color[0] !== 'number' : color.length / 4 === pointsCount;\n var positionAttr = this.attributes.position;\n var colorAttr = this.attributes.color;\n var offsetAttr = this.attributes.offset;\n var normalAttr = this.attributes.normal;\n var indices = this.indices;\n var vertexOffset = this._vertexOffset;\n var pointColor;\n\n for (var k = 0; k < pointsCount; k++) {\n if (is2DArray) {\n point = points[k + arrayOffset];\n\n if (notSharingColor) {\n pointColor = color[k + arrayOffset];\n } else {\n pointColor = color;\n }\n } else {\n var k2 = k * 2 + arrayOffset;\n point = point || [];\n point[0] = points[k2];\n point[1] = points[k2 + 1];\n\n if (notSharingColor) {\n var k4 = k * 4 + arrayOffset;\n pointColor = pointColor || [];\n pointColor[0] = color[k4];\n pointColor[1] = color[k4 + 1];\n pointColor[2] = color[k4 + 2];\n pointColor[3] = color[k4 + 3];\n } else {\n pointColor = color;\n }\n }\n\n if (!this.useNativeLine) {\n var offset;\n\n if (k < pointsCount - 1) {\n if (is2DArray) {\n vec2.copy(nextPoint, points[k + 1]);\n } else {\n var k2 = (k + 1) * 2 + arrayOffset;\n nextPoint = nextPoint || [];\n nextPoint[0] = points[k2];\n nextPoint[1] = points[k2 + 1];\n } // TODO In case dir is (0, 0)\n // TODO miterLimit\n\n\n if (k > 0) {\n vec2.sub(dirA, point, prevPoint);\n vec2.sub(dirB, nextPoint, point);\n vec2.normalize(dirA, dirA);\n vec2.normalize(dirB, dirB);\n vec2.add(tangent, dirA, dirB);\n vec2.normalize(tangent, tangent);\n var miter = lineWidth / 2 * Math.min(1 / vec2.dot(dirA, tangent), 2);\n normal[0] = -tangent[1];\n normal[1] = tangent[0];\n offset = miter;\n } else {\n vec2.sub(dirA, nextPoint, point);\n vec2.normalize(dirA, dirA);\n normal[0] = -dirA[1];\n normal[1] = dirA[0];\n offset = lineWidth / 2;\n }\n } else {\n vec2.sub(dirA, point, prevPoint);\n vec2.normalize(dirA, dirA);\n normal[0] = -dirA[1];\n normal[1] = dirA[0];\n offset = lineWidth / 2;\n }\n\n normalAttr.set(vertexOffset, normal);\n normalAttr.set(vertexOffset + 1, normal);\n offsetAttr.set(vertexOffset, offset);\n offsetAttr.set(vertexOffset + 1, -offset);\n vec2.copy(prevPoint, point);\n positionAttr.set(vertexOffset, point);\n positionAttr.set(vertexOffset + 1, point);\n colorAttr.set(vertexOffset, pointColor);\n colorAttr.set(vertexOffset + 1, pointColor);\n vertexOffset += 2;\n } else {\n if (k > 1) {\n positionAttr.copy(vertexOffset, vertexOffset - 1);\n colorAttr.copy(vertexOffset, vertexOffset - 1);\n vertexOffset++;\n }\n }\n\n if (!this.useNativeLine) {\n if (k > 0) {\n var idx3 = this._faceOffset * 3;\n var indices = this.indices; // 0-----2\n // 1-----3\n // 0->1->2, 1->3->2\n\n indices[idx3] = vertexOffset - 4;\n indices[idx3 + 1] = vertexOffset - 3;\n indices[idx3 + 2] = vertexOffset - 2;\n indices[idx3 + 3] = vertexOffset - 3;\n indices[idx3 + 4] = vertexOffset - 1;\n indices[idx3 + 5] = vertexOffset - 2;\n this._faceOffset += 2;\n }\n } else {\n colorAttr.set(vertexOffset, pointColor);\n positionAttr.set(vertexOffset, point);\n vertexOffset++;\n }\n }\n\n this._vertexOffset = vertexOffset;\n };\n }(),\n\n /**\n * Set color of single line.\n */\n setItemColor: function (idx, color) {\n var startOffset = this._itemVertexOffsets[idx];\n var endOffset = idx < this._itemVertexOffsets.length - 1 ? this._itemVertexOffsets[idx + 1] : this._vertexOffset;\n\n for (var i = startOffset; i < endOffset; i++) {\n this.attributes.color.set(i, color);\n }\n\n this.dirty('color');\n }\n});\necharts.util.defaults(LinesGeometry.prototype, dynamicConvertMixin);\nexport default LinesGeometry;","export default \"@export ecgl.forceAtlas2.updateNodeRepulsion\\n\\n#define NODE_COUNT 0\\n\\nuniform sampler2D positionTex;\\n\\nuniform vec2 textureSize;\\nuniform float gravity;\\nuniform float scaling;\\nuniform vec2 gravityCenter;\\n\\nuniform bool strongGravityMode;\\nuniform bool preventOverlap;\\n\\nvarying vec2 v_Texcoord;\\n\\nvoid main() {\\n\\n vec4 n0 = texture2D(positionTex, v_Texcoord);\\n\\n vec2 force = vec2(0.0);\\n for (int i = 0; i < NODE_COUNT; i++) {\\n vec2 uv = vec2(\\n mod(float(i), textureSize.x) / (textureSize.x - 1.0),\\n floor(float(i) / textureSize.x) / (textureSize.y - 1.0)\\n );\\n vec4 n1 = texture2D(positionTex, uv);\\n\\n vec2 dir = n0.xy - n1.xy;\\n float d2 = dot(dir, dir);\\n\\n if (d2 > 0.0) {\\n float factor = 0.0;\\n if (preventOverlap) {\\n float d = sqrt(d2);\\n d = d - n0.w - n1.w;\\n if (d > 0.0) {\\n factor = scaling * n0.z * n1.z / (d * d);\\n }\\n else if (d < 0.0) {\\n factor = scaling * 100.0 * n0.z * n1.z;\\n }\\n }\\n else {\\n factor = scaling * n0.z * n1.z / d2;\\n }\\n force += dir * factor;\\n }\\n }\\n\\n vec2 dir = gravityCenter - n0.xy;\\n float d = 1.0;\\n if (!strongGravityMode) {\\n d = length(dir);\\n }\\n\\n force += dir * n0.z * gravity / (d + 1.0);\\n\\n gl_FragColor = vec4(force, 0.0, 1.0);\\n}\\n@end\\n\\n@export ecgl.forceAtlas2.updateEdgeAttraction.vertex\\n\\nattribute vec2 node1;\\nattribute vec2 node2;\\nattribute float weight;\\n\\nuniform sampler2D positionTex;\\nuniform float edgeWeightInfluence;\\nuniform bool preventOverlap;\\nuniform bool linLogMode;\\n\\nuniform vec2 windowSize: WINDOW_SIZE;\\n\\nvarying vec2 v_Force;\\n\\nvoid main() {\\n\\n vec4 n0 = texture2D(positionTex, node1);\\n vec4 n1 = texture2D(positionTex, node2);\\n\\n vec2 dir = n1.xy - n0.xy;\\n float d = length(dir);\\n float w;\\n if (edgeWeightInfluence == 0.0) {\\n w = 1.0;\\n }\\n else if (edgeWeightInfluence == 1.0) {\\n w = weight;\\n }\\n else {\\n w = pow(weight, edgeWeightInfluence);\\n }\\n vec2 offset = vec2(1.0 / windowSize.x, 1.0 / windowSize.y);\\n vec2 scale = vec2((windowSize.x - 1.0) / windowSize.x, (windowSize.y - 1.0) / windowSize.y);\\n vec2 pos = node1 * scale * 2.0 - 1.0;\\n gl_Position = vec4(pos + offset, 0.0, 1.0);\\n gl_PointSize = 1.0;\\n\\n float factor;\\n if (preventOverlap) {\\n d = d - n1.w - n0.w;\\n }\\n if (d <= 0.0) {\\n v_Force = vec2(0.0);\\n return;\\n }\\n\\n if (linLogMode) {\\n factor = w * log(d) / d;\\n }\\n else {\\n factor = w;\\n }\\n v_Force = dir * factor;\\n}\\n@end\\n\\n@export ecgl.forceAtlas2.updateEdgeAttraction.fragment\\n\\nvarying vec2 v_Force;\\n\\nvoid main() {\\n gl_FragColor = vec4(v_Force, 0.0, 0.0);\\n}\\n@end\\n\\n@export ecgl.forceAtlas2.calcWeightedSum.vertex\\n\\nattribute vec2 node;\\n\\nvarying vec2 v_NodeUv;\\n\\nvoid main() {\\n\\n v_NodeUv = node;\\n gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\\n gl_PointSize = 1.0;\\n}\\n@end\\n\\n@export ecgl.forceAtlas2.calcWeightedSum.fragment\\n\\nvarying vec2 v_NodeUv;\\n\\nuniform sampler2D positionTex;\\nuniform sampler2D forceTex;\\nuniform sampler2D forcePrevTex;\\n\\nvoid main() {\\n vec2 force = texture2D(forceTex, v_NodeUv).rg;\\n vec2 forcePrev = texture2D(forcePrevTex, v_NodeUv).rg;\\n\\n float mass = texture2D(positionTex, v_NodeUv).z;\\n float swing = length(force - forcePrev) * mass;\\n float traction = length(force + forcePrev) * 0.5 * mass;\\n\\n gl_FragColor = vec4(swing, traction, 0.0, 0.0);\\n}\\n@end\\n\\n@export ecgl.forceAtlas2.calcGlobalSpeed\\n\\nuniform sampler2D globalSpeedPrevTex;\\nuniform sampler2D weightedSumTex;\\nuniform float jitterTolerence;\\n\\nvoid main() {\\n vec2 weightedSum = texture2D(weightedSumTex, vec2(0.5)).xy;\\n float prevGlobalSpeed = texture2D(globalSpeedPrevTex, vec2(0.5)).x;\\n float globalSpeed = jitterTolerence * jitterTolerence\\n * weightedSum.y / weightedSum.x;\\n if (prevGlobalSpeed > 0.0) {\\n globalSpeed = min(globalSpeed / prevGlobalSpeed, 1.5) * prevGlobalSpeed;\\n }\\n gl_FragColor = vec4(globalSpeed, 0.0, 0.0, 1.0);\\n}\\n@end\\n\\n@export ecgl.forceAtlas2.updatePosition\\n\\nuniform sampler2D forceTex;\\nuniform sampler2D forcePrevTex;\\nuniform sampler2D positionTex;\\nuniform sampler2D globalSpeedTex;\\n\\nvarying vec2 v_Texcoord;\\n\\nvoid main() {\\n vec2 force = texture2D(forceTex, v_Texcoord).xy;\\n vec2 forcePrev = texture2D(forcePrevTex, v_Texcoord).xy;\\n vec4 node = texture2D(positionTex, v_Texcoord);\\n\\n float globalSpeed = texture2D(globalSpeedTex, vec2(0.5)).r;\\n float swing = length(force - forcePrev);\\n float speed = 0.1 * globalSpeed / (0.1 + globalSpeed * sqrt(swing));\\n\\n float df = length(force);\\n if (df > 0.0) {\\n speed = min(df * speed, 10.0) / df;\\n\\n gl_FragColor = vec4(node.xy + speed * force, node.zw);\\n }\\n else {\\n gl_FragColor = node;\\n }\\n}\\n@end\\n\\n@export ecgl.forceAtlas2.edges.vertex\\nuniform mat4 worldViewProjection : WORLDVIEWPROJECTION;\\n\\nattribute vec2 node;\\nattribute vec4 a_Color : COLOR;\\nvarying vec4 v_Color;\\n\\nuniform sampler2D positionTex;\\n\\nvoid main()\\n{\\n gl_Position = worldViewProjection * vec4(\\n texture2D(positionTex, node).xy, -10.0, 1.0\\n );\\n v_Color = a_Color;\\n}\\n@end\\n\\n@export ecgl.forceAtlas2.edges.fragment\\nuniform vec4 color : [1.0, 1.0, 1.0, 1.0];\\nvarying vec4 v_Color;\\nvoid main() {\\n gl_FragColor = color * v_Color;\\n}\\n@end\";","import graphicGL from '../../util/graphicGL';\nimport Pass from 'claygl/src/compositor/Pass';\nimport FrameBuffer from 'claygl/src/FrameBuffer';\nimport forceAtlas2Code from './forceAtlas2.glsl.js';\ngraphicGL.Shader.import(forceAtlas2Code);\nvar defaultConfigs = {\n repulsionByDegree: true,\n linLogMode: false,\n strongGravityMode: false,\n gravity: 1.0,\n scaling: 1.0,\n edgeWeightInfluence: 1.0,\n jitterTolerence: 0.1,\n preventOverlap: false,\n dissuadeHubs: false,\n gravityCenter: null\n};\n\nfunction ForceAtlas2GPU(options) {\n var textureOpt = {\n type: graphicGL.Texture.FLOAT,\n minFilter: graphicGL.Texture.NEAREST,\n magFilter: graphicGL.Texture.NEAREST\n };\n this._positionSourceTex = new graphicGL.Texture2D(textureOpt);\n this._positionSourceTex.flipY = false;\n this._positionTex = new graphicGL.Texture2D(textureOpt);\n this._positionPrevTex = new graphicGL.Texture2D(textureOpt);\n this._forceTex = new graphicGL.Texture2D(textureOpt);\n this._forcePrevTex = new graphicGL.Texture2D(textureOpt);\n this._weightedSumTex = new graphicGL.Texture2D(textureOpt);\n this._weightedSumTex.width = this._weightedSumTex.height = 1;\n this._globalSpeedTex = new graphicGL.Texture2D(textureOpt);\n this._globalSpeedPrevTex = new graphicGL.Texture2D(textureOpt);\n this._globalSpeedTex.width = this._globalSpeedTex.height = 1;\n this._globalSpeedPrevTex.width = this._globalSpeedPrevTex.height = 1;\n this._nodeRepulsionPass = new Pass({\n fragment: graphicGL.Shader.source('ecgl.forceAtlas2.updateNodeRepulsion')\n });\n this._positionPass = new Pass({\n fragment: graphicGL.Shader.source('ecgl.forceAtlas2.updatePosition')\n });\n this._globalSpeedPass = new Pass({\n fragment: graphicGL.Shader.source('ecgl.forceAtlas2.calcGlobalSpeed')\n });\n this._copyPass = new Pass({\n fragment: graphicGL.Shader.source('clay.compositor.output')\n });\n\n var additiveBlend = function (gl) {\n gl.blendEquation(gl.FUNC_ADD);\n gl.blendFunc(gl.ONE, gl.ONE);\n };\n\n this._edgeForceMesh = new graphicGL.Mesh({\n geometry: new graphicGL.Geometry({\n attributes: {\n node1: new graphicGL.Geometry.Attribute('node1', 'float', 2),\n node2: new graphicGL.Geometry.Attribute('node2', 'float', 2),\n weight: new graphicGL.Geometry.Attribute('weight', 'float', 1)\n },\n dynamic: true,\n mainAttribute: 'node1'\n }),\n material: new graphicGL.Material({\n transparent: true,\n shader: graphicGL.createShader('ecgl.forceAtlas2.updateEdgeAttraction'),\n blend: additiveBlend,\n depthMask: false,\n depthText: false\n }),\n mode: graphicGL.Mesh.POINTS\n });\n this._weightedSumMesh = new graphicGL.Mesh({\n geometry: new graphicGL.Geometry({\n attributes: {\n node: new graphicGL.Geometry.Attribute('node', 'float', 2)\n },\n dynamic: true,\n mainAttribute: 'node'\n }),\n material: new graphicGL.Material({\n transparent: true,\n shader: graphicGL.createShader('ecgl.forceAtlas2.calcWeightedSum'),\n blend: additiveBlend,\n depthMask: false,\n depthText: false\n }),\n mode: graphicGL.Mesh.POINTS\n });\n this._framebuffer = new FrameBuffer({\n depthBuffer: false\n });\n this._dummyCamera = new graphicGL.OrthographicCamera({\n left: -1,\n right: 1,\n top: 1,\n bottom: -1,\n near: 0,\n far: 100\n });\n this._globalSpeed = 0;\n}\n\nForceAtlas2GPU.prototype.updateOption = function (options) {\n // Default config\n for (var name in defaultConfigs) {\n this[name] = defaultConfigs[name];\n } // Config according to data scale\n\n\n var nNodes = this._nodes.length;\n\n if (nNodes > 50000) {\n this.jitterTolerence = 10;\n } else if (nNodes > 5000) {\n this.jitterTolerence = 1;\n } else {\n this.jitterTolerence = 0.1;\n }\n\n if (nNodes > 100) {\n this.scaling = 2.0;\n } else {\n this.scaling = 10.0;\n } // this.edgeWeightInfluence = 1;\n // this.gravity = 1;\n // this.strongGravityMode = false;\n\n\n if (options) {\n for (var name in defaultConfigs) {\n if (options[name] != null) {\n this[name] = options[name];\n }\n }\n }\n\n if (this.repulsionByDegree) {\n var positionBuffer = this._positionSourceTex.pixels;\n\n for (var i = 0; i < this._nodes.length; i++) {\n positionBuffer[i * 4 + 2] = (this._nodes[i].degree || 0) + 1;\n }\n }\n};\n\nForceAtlas2GPU.prototype._updateGravityCenter = function (options) {\n var nodes = this._nodes;\n var edges = this._edges;\n\n if (!this.gravityCenter) {\n var min = [Infinity, Infinity];\n var max = [-Infinity, -Infinity];\n\n for (var i = 0; i < nodes.length; i++) {\n min[0] = Math.min(nodes[i].x, min[0]);\n min[1] = Math.min(nodes[i].y, min[1]);\n max[0] = Math.max(nodes[i].x, max[0]);\n max[1] = Math.max(nodes[i].y, max[1]);\n }\n\n this._gravityCenter = [(min[0] + max[0]) * 0.5, (min[1] + max[1]) * 0.5];\n } else {\n this._gravityCenter = this.gravityCenter;\n } // Update inDegree, outDegree\n\n\n for (var i = 0; i < edges.length; i++) {\n var node1 = edges[i].node1;\n var node2 = edges[i].node2;\n nodes[node1].degree = (nodes[node1].degree || 0) + 1;\n nodes[node2].degree = (nodes[node2].degree || 0) + 1;\n }\n};\n/**\n * @param {Array.