Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/src/packages/assets/threejs/r73/CanvasRenderer.js
Views: 687
/*1* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45/**6* @author mrdoob / http://mrdoob.com/7*/89THREE.SpriteCanvasMaterial = function ( parameters ) {1011THREE.Material.call( this );1213this.type = 'SpriteCanvasMaterial';1415this.color = new THREE.Color( 0xffffff );16this.program = function ( context, color ) {};1718this.setValues( parameters );1920};2122THREE.SpriteCanvasMaterial.prototype = Object.create( THREE.Material.prototype );23THREE.SpriteCanvasMaterial.prototype.constructor = THREE.SpriteCanvasMaterial;2425THREE.SpriteCanvasMaterial.prototype.clone = function () {2627var material = new THREE.SpriteCanvasMaterial();2829material.copy( this );30material.color.copy( this.color );31material.program = this.program;3233return material;3435};3637//3839THREE.CanvasRenderer = function ( parameters ) {4041console.log( 'THREE.CanvasRenderer', THREE.REVISION );4243parameters = parameters || {};4445var _this = this,46_renderData, _elements, _lights,47_projector = new THREE.Projector(),4849_canvas = parameters.canvas !== undefined50? parameters.canvas51: document.createElement( 'canvas' ),5253_canvasWidth = _canvas.width,54_canvasHeight = _canvas.height,55_canvasWidthHalf = Math.floor( _canvasWidth / 2 ),56_canvasHeightHalf = Math.floor( _canvasHeight / 2 ),5758_viewportX = 0,59_viewportY = 0,60_viewportWidth = _canvasWidth,61_viewportHeight = _canvasHeight,6263pixelRatio = 1,6465_context = _canvas.getContext( '2d', {66alpha: parameters.alpha === true67} ),6869_clearColor = new THREE.Color( 0x000000 ),70_clearAlpha = parameters.alpha === true ? 0 : 1,7172_contextGlobalAlpha = 1,73_contextGlobalCompositeOperation = 0,74_contextStrokeStyle = null,75_contextFillStyle = null,76_contextLineWidth = null,77_contextLineCap = null,78_contextLineJoin = null,79_contextLineDash = [],8081_camera,8283_v1, _v2, _v3, _v4,84_v5 = new THREE.RenderableVertex(),85_v6 = new THREE.RenderableVertex(),8687_v1x, _v1y, _v2x, _v2y, _v3x, _v3y,88_v4x, _v4y, _v5x, _v5y, _v6x, _v6y,8990_color = new THREE.Color(),91_color1 = new THREE.Color(),92_color2 = new THREE.Color(),93_color3 = new THREE.Color(),94_color4 = new THREE.Color(),9596_diffuseColor = new THREE.Color(),97_emissiveColor = new THREE.Color(),9899_lightColor = new THREE.Color(),100101_patterns = {},102103_image, _uvs,104_uv1x, _uv1y, _uv2x, _uv2y, _uv3x, _uv3y,105106_clipBox = new THREE.Box2(),107_clearBox = new THREE.Box2(),108_elemBox = new THREE.Box2(),109110_ambientLight = new THREE.Color(),111_directionalLights = new THREE.Color(),112_pointLights = new THREE.Color(),113114_vector3 = new THREE.Vector3(), // Needed for PointLight115_centroid = new THREE.Vector3(),116_normal = new THREE.Vector3(),117_normalViewMatrix = new THREE.Matrix3();118119// dash+gap fallbacks for Firefox and everything else120121if ( _context.setLineDash === undefined ) {122123_context.setLineDash = function () {};124125}126127this.domElement = _canvas;128129this.autoClear = true;130this.sortObjects = true;131this.sortElements = true;132133this.info = {134135render: {136137vertices: 0,138faces: 0139140}141142};143144// WebGLRenderer compatibility145146this.supportsVertexTextures = function () {};147this.setFaceCulling = function () {};148149// API150151this.getContext = function () {152153return _context;154155};156157this.getContextAttributes = function () {158159return _context.getContextAttributes();160161};162163this.getPixelRatio = function () {164165return pixelRatio;166167};168169this.setPixelRatio = function ( value ) {170171if ( value !== undefined ) pixelRatio = value;172173};174175this.setSize = function ( width, height, updateStyle ) {176177_canvasWidth = width * pixelRatio;178_canvasHeight = height * pixelRatio;179180_canvas.width = _canvasWidth;181_canvas.height = _canvasHeight;182183_canvasWidthHalf = Math.floor( _canvasWidth / 2 );184_canvasHeightHalf = Math.floor( _canvasHeight / 2 );185186if ( updateStyle !== false ) {187188_canvas.style.width = width + 'px';189_canvas.style.height = height + 'px';190191}192193_clipBox.min.set( - _canvasWidthHalf, - _canvasHeightHalf );194_clipBox.max.set( _canvasWidthHalf, _canvasHeightHalf );195196_clearBox.min.set( - _canvasWidthHalf, - _canvasHeightHalf );197_clearBox.max.set( _canvasWidthHalf, _canvasHeightHalf );198199_contextGlobalAlpha = 1;200_contextGlobalCompositeOperation = 0;201_contextStrokeStyle = null;202_contextFillStyle = null;203_contextLineWidth = null;204_contextLineCap = null;205_contextLineJoin = null;206207this.setViewport( 0, 0, width, height );208209};210211this.setViewport = function ( x, y, width, height ) {212213_viewportX = x * pixelRatio;214_viewportY = y * pixelRatio;215216_viewportWidth = width * pixelRatio;217_viewportHeight = height * pixelRatio;218219};220221this.setScissor = function () {};222this.enableScissorTest = function () {};223224this.setClearColor = function ( color, alpha ) {225226_clearColor.set( color );227_clearAlpha = alpha !== undefined ? alpha : 1;228229_clearBox.min.set( - _canvasWidthHalf, - _canvasHeightHalf );230_clearBox.max.set( _canvasWidthHalf, _canvasHeightHalf );231232};233234this.setClearColorHex = function ( hex, alpha ) {235236console.warn( 'THREE.CanvasRenderer: .setClearColorHex() is being removed. Use .setClearColor() instead.' );237this.setClearColor( hex, alpha );238239};240241this.getClearColor = function () {242243return _clearColor;244245};246247this.getClearAlpha = function () {248249return _clearAlpha;250251};252253this.getMaxAnisotropy = function () {254255return 0;256257};258259this.clear = function () {260261if ( _clearBox.empty() === false ) {262263_clearBox.intersect( _clipBox );264_clearBox.expandByScalar( 2 );265266_clearBox.min.x = _clearBox.min.x + _canvasWidthHalf;267_clearBox.min.y = - _clearBox.min.y + _canvasHeightHalf; // higher y value !268_clearBox.max.x = _clearBox.max.x + _canvasWidthHalf;269_clearBox.max.y = - _clearBox.max.y + _canvasHeightHalf; // lower y value !270271if ( _clearAlpha < 1 ) {272273_context.clearRect(274_clearBox.min.x | 0,275_clearBox.max.y | 0,276( _clearBox.max.x - _clearBox.min.x ) | 0,277( _clearBox.min.y - _clearBox.max.y ) | 0278);279280}281282if ( _clearAlpha > 0 ) {283284setBlending( THREE.NormalBlending );285setOpacity( 1 );286287setFillStyle( 'rgba(' + Math.floor( _clearColor.r * 255 ) + ',' + Math.floor( _clearColor.g * 255 ) + ',' + Math.floor( _clearColor.b * 255 ) + ',' + _clearAlpha + ')' );288289_context.fillRect(290_clearBox.min.x | 0,291_clearBox.max.y | 0,292( _clearBox.max.x - _clearBox.min.x ) | 0,293( _clearBox.min.y - _clearBox.max.y ) | 0294);295296}297298_clearBox.makeEmpty();299300}301302};303304// compatibility305306this.clearColor = function () {};307this.clearDepth = function () {};308this.clearStencil = function () {};309310this.render = function ( scene, camera ) {311312if ( camera instanceof THREE.Camera === false ) {313314console.error( 'THREE.CanvasRenderer.render: camera is not an instance of THREE.Camera.' );315return;316317}318319if ( this.autoClear === true ) this.clear();320321_this.info.render.vertices = 0;322_this.info.render.faces = 0;323324_context.setTransform( _viewportWidth / _canvasWidth, 0, 0, - _viewportHeight / _canvasHeight, _viewportX, _canvasHeight - _viewportY );325_context.translate( _canvasWidthHalf, _canvasHeightHalf );326327_renderData = _projector.projectScene( scene, camera, this.sortObjects, this.sortElements );328_elements = _renderData.elements;329_lights = _renderData.lights;330_camera = camera;331332_normalViewMatrix.getNormalMatrix( camera.matrixWorldInverse );333334/* DEBUG335setFillStyle( 'rgba( 0, 255, 255, 0.5 )' );336_context.fillRect( _clipBox.min.x, _clipBox.min.y, _clipBox.max.x - _clipBox.min.x, _clipBox.max.y - _clipBox.min.y );337*/338339calculateLights();340341for ( var e = 0, el = _elements.length; e < el; e ++ ) {342343var element = _elements[ e ];344345var material = element.material;346347if ( material === undefined || material.opacity === 0 ) continue;348349_elemBox.makeEmpty();350351if ( element instanceof THREE.RenderableSprite ) {352353_v1 = element;354_v1.x *= _canvasWidthHalf; _v1.y *= _canvasHeightHalf;355356renderSprite( _v1, element, material );357358} else if ( element instanceof THREE.RenderableLine ) {359360_v1 = element.v1; _v2 = element.v2;361362_v1.positionScreen.x *= _canvasWidthHalf; _v1.positionScreen.y *= _canvasHeightHalf;363_v2.positionScreen.x *= _canvasWidthHalf; _v2.positionScreen.y *= _canvasHeightHalf;364365_elemBox.setFromPoints( [366_v1.positionScreen,367_v2.positionScreen368] );369370if ( _clipBox.isIntersectionBox( _elemBox ) === true ) {371372renderLine( _v1, _v2, element, material );373374}375376} else if ( element instanceof THREE.RenderableFace ) {377378_v1 = element.v1; _v2 = element.v2; _v3 = element.v3;379380if ( _v1.positionScreen.z < - 1 || _v1.positionScreen.z > 1 ) continue;381if ( _v2.positionScreen.z < - 1 || _v2.positionScreen.z > 1 ) continue;382if ( _v3.positionScreen.z < - 1 || _v3.positionScreen.z > 1 ) continue;383384_v1.positionScreen.x *= _canvasWidthHalf; _v1.positionScreen.y *= _canvasHeightHalf;385_v2.positionScreen.x *= _canvasWidthHalf; _v2.positionScreen.y *= _canvasHeightHalf;386_v3.positionScreen.x *= _canvasWidthHalf; _v3.positionScreen.y *= _canvasHeightHalf;387388if ( material.overdraw > 0 ) {389390expand( _v1.positionScreen, _v2.positionScreen, material.overdraw );391expand( _v2.positionScreen, _v3.positionScreen, material.overdraw );392expand( _v3.positionScreen, _v1.positionScreen, material.overdraw );393394}395396_elemBox.setFromPoints( [397_v1.positionScreen,398_v2.positionScreen,399_v3.positionScreen400] );401402if ( _clipBox.isIntersectionBox( _elemBox ) === true ) {403404renderFace3( _v1, _v2, _v3, 0, 1, 2, element, material );405406}407408}409410/* DEBUG411setLineWidth( 1 );412setStrokeStyle( 'rgba( 0, 255, 0, 0.5 )' );413_context.strokeRect( _elemBox.min.x, _elemBox.min.y, _elemBox.max.x - _elemBox.min.x, _elemBox.max.y - _elemBox.min.y );414*/415416_clearBox.union( _elemBox );417418}419420/* DEBUG421setLineWidth( 1 );422setStrokeStyle( 'rgba( 255, 0, 0, 0.5 )' );423_context.strokeRect( _clearBox.min.x, _clearBox.min.y, _clearBox.max.x - _clearBox.min.x, _clearBox.max.y - _clearBox.min.y );424*/425426_context.setTransform( 1, 0, 0, 1, 0, 0 );427428};429430//431432function calculateLights() {433434_ambientLight.setRGB( 0, 0, 0 );435_directionalLights.setRGB( 0, 0, 0 );436_pointLights.setRGB( 0, 0, 0 );437438for ( var l = 0, ll = _lights.length; l < ll; l ++ ) {439440var light = _lights[ l ];441var lightColor = light.color;442443if ( light instanceof THREE.AmbientLight ) {444445_ambientLight.add( lightColor );446447} else if ( light instanceof THREE.DirectionalLight ) {448449// for sprites450451_directionalLights.add( lightColor );452453} else if ( light instanceof THREE.PointLight ) {454455// for sprites456457_pointLights.add( lightColor );458459}460461}462463}464465function calculateLight( position, normal, color ) {466467for ( var l = 0, ll = _lights.length; l < ll; l ++ ) {468469var light = _lights[ l ];470471_lightColor.copy( light.color );472473if ( light instanceof THREE.DirectionalLight ) {474475var lightPosition = _vector3.setFromMatrixPosition( light.matrixWorld ).normalize();476477var amount = normal.dot( lightPosition );478479if ( amount <= 0 ) continue;480481amount *= light.intensity;482483color.add( _lightColor.multiplyScalar( amount ) );484485} else if ( light instanceof THREE.PointLight ) {486487var lightPosition = _vector3.setFromMatrixPosition( light.matrixWorld );488489var amount = normal.dot( _vector3.subVectors( lightPosition, position ).normalize() );490491if ( amount <= 0 ) continue;492493amount *= light.distance == 0 ? 1 : 1 - Math.min( position.distanceTo( lightPosition ) / light.distance, 1 );494495if ( amount == 0 ) continue;496497amount *= light.intensity;498499color.add( _lightColor.multiplyScalar( amount ) );500501}502503}504505}506507function renderSprite( v1, element, material ) {508509setOpacity( material.opacity );510setBlending( material.blending );511512var scaleX = element.scale.x * _canvasWidthHalf;513var scaleY = element.scale.y * _canvasHeightHalf;514515var dist = 0.5 * Math.sqrt( scaleX * scaleX + scaleY * scaleY ); // allow for rotated sprite516_elemBox.min.set( v1.x - dist, v1.y - dist );517_elemBox.max.set( v1.x + dist, v1.y + dist );518519if ( material instanceof THREE.SpriteMaterial ) {520521var texture = material.map;522523if ( texture !== null ) {524525var pattern = _patterns[ texture.id ];526527if ( pattern === undefined || pattern.version !== texture.version ) {528529pattern = textureToPattern( texture );530_patterns[ texture.id ] = pattern;531532}533534if ( pattern.canvas !== undefined ) {535536setFillStyle( pattern.canvas );537538var bitmap = texture.image;539540var ox = bitmap.width * texture.offset.x;541var oy = bitmap.height * texture.offset.y;542543var sx = bitmap.width * texture.repeat.x;544var sy = bitmap.height * texture.repeat.y;545546var cx = scaleX / sx;547var cy = scaleY / sy;548549_context.save();550_context.translate( v1.x, v1.y );551if ( material.rotation !== 0 ) _context.rotate( material.rotation );552_context.translate( - scaleX / 2, - scaleY / 2 );553_context.scale( cx, cy );554_context.translate( - ox, - oy );555_context.fillRect( ox, oy, sx, sy );556_context.restore();557558}559560} else {561562// no texture563564setFillStyle( material.color.getStyle() );565566_context.save();567_context.translate( v1.x, v1.y );568if ( material.rotation !== 0 ) _context.rotate( material.rotation );569_context.scale( scaleX, - scaleY );570_context.fillRect( - 0.5, - 0.5, 1, 1 );571_context.restore();572573}574575} else if ( material instanceof THREE.SpriteCanvasMaterial ) {576577setStrokeStyle( material.color.getStyle() );578setFillStyle( material.color.getStyle() );579580_context.save();581_context.translate( v1.x, v1.y );582if ( material.rotation !== 0 ) _context.rotate( material.rotation );583_context.scale( scaleX, scaleY );584585material.program( _context );586587_context.restore();588589}590591/* DEBUG592setStrokeStyle( 'rgb(255,255,0)' );593_context.beginPath();594_context.moveTo( v1.x - 10, v1.y );595_context.lineTo( v1.x + 10, v1.y );596_context.moveTo( v1.x, v1.y - 10 );597_context.lineTo( v1.x, v1.y + 10 );598_context.stroke();599*/600601}602603function renderLine( v1, v2, element, material ) {604605setOpacity( material.opacity );606setBlending( material.blending );607608_context.beginPath();609_context.moveTo( v1.positionScreen.x, v1.positionScreen.y );610_context.lineTo( v2.positionScreen.x, v2.positionScreen.y );611612if ( material instanceof THREE.LineBasicMaterial ) {613614setLineWidth( material.linewidth );615setLineCap( material.linecap );616setLineJoin( material.linejoin );617618if ( material.vertexColors !== THREE.VertexColors ) {619620setStrokeStyle( material.color.getStyle() );621622} else {623624var colorStyle1 = element.vertexColors[ 0 ].getStyle();625var colorStyle2 = element.vertexColors[ 1 ].getStyle();626627if ( colorStyle1 === colorStyle2 ) {628629setStrokeStyle( colorStyle1 );630631} else {632633try {634635var grad = _context.createLinearGradient(636v1.positionScreen.x,637v1.positionScreen.y,638v2.positionScreen.x,639v2.positionScreen.y640);641grad.addColorStop( 0, colorStyle1 );642grad.addColorStop( 1, colorStyle2 );643644} catch ( exception ) {645646grad = colorStyle1;647648}649650setStrokeStyle( grad );651652}653654}655656_context.stroke();657_elemBox.expandByScalar( material.linewidth * 2 );658659} else if ( material instanceof THREE.LineDashedMaterial ) {660661setLineWidth( material.linewidth );662setLineCap( material.linecap );663setLineJoin( material.linejoin );664setStrokeStyle( material.color.getStyle() );665setLineDash( [ material.dashSize, material.gapSize ] );666667_context.stroke();668669_elemBox.expandByScalar( material.linewidth * 2 );670671setLineDash( [] );672673}674675}676677function renderFace3( v1, v2, v3, uv1, uv2, uv3, element, material ) {678679_this.info.render.vertices += 3;680_this.info.render.faces ++;681682setOpacity( material.opacity );683setBlending( material.blending );684685_v1x = v1.positionScreen.x; _v1y = v1.positionScreen.y;686_v2x = v2.positionScreen.x; _v2y = v2.positionScreen.y;687_v3x = v3.positionScreen.x; _v3y = v3.positionScreen.y;688689drawTriangle( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y );690691if ( ( material instanceof THREE.MeshLambertMaterial || material instanceof THREE.MeshPhongMaterial ) && material.map === null ) {692693_diffuseColor.copy( material.color );694_emissiveColor.copy( material.emissive );695696if ( material.vertexColors === THREE.FaceColors ) {697698_diffuseColor.multiply( element.color );699700}701702_color.copy( _ambientLight );703704_centroid.copy( v1.positionWorld ).add( v2.positionWorld ).add( v3.positionWorld ).divideScalar( 3 );705706calculateLight( _centroid, element.normalModel, _color );707708_color.multiply( _diffuseColor ).add( _emissiveColor );709710material.wireframe === true711? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin )712: fillPath( _color );713714} else if ( material instanceof THREE.MeshBasicMaterial ||715material instanceof THREE.MeshLambertMaterial ||716material instanceof THREE.MeshPhongMaterial ) {717718if ( material.map !== null ) {719720var mapping = material.map.mapping;721722if ( mapping === THREE.UVMapping ) {723724_uvs = element.uvs;725patternPath( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _uvs[ uv1 ].x, _uvs[ uv1 ].y, _uvs[ uv2 ].x, _uvs[ uv2 ].y, _uvs[ uv3 ].x, _uvs[ uv3 ].y, material.map );726727}728729} else if ( material.envMap !== null ) {730731if ( material.envMap.mapping === THREE.SphericalReflectionMapping ) {732733_normal.copy( element.vertexNormalsModel[ uv1 ] ).applyMatrix3( _normalViewMatrix );734_uv1x = 0.5 * _normal.x + 0.5;735_uv1y = 0.5 * _normal.y + 0.5;736737_normal.copy( element.vertexNormalsModel[ uv2 ] ).applyMatrix3( _normalViewMatrix );738_uv2x = 0.5 * _normal.x + 0.5;739_uv2y = 0.5 * _normal.y + 0.5;740741_normal.copy( element.vertexNormalsModel[ uv3 ] ).applyMatrix3( _normalViewMatrix );742_uv3x = 0.5 * _normal.x + 0.5;743_uv3y = 0.5 * _normal.y + 0.5;744745patternPath( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _uv1x, _uv1y, _uv2x, _uv2y, _uv3x, _uv3y, material.envMap );746747}748749} else {750751_color.copy( material.color );752753if ( material.vertexColors === THREE.FaceColors ) {754755_color.multiply( element.color );756757}758759material.wireframe === true760? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin )761: fillPath( _color );762763}764765} else if ( material instanceof THREE.MeshNormalMaterial ) {766767_normal.copy( element.normalModel ).applyMatrix3( _normalViewMatrix );768769_color.setRGB( _normal.x, _normal.y, _normal.z ).multiplyScalar( 0.5 ).addScalar( 0.5 );770771material.wireframe === true772? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin )773: fillPath( _color );774775} else {776777_color.setRGB( 1, 1, 1 );778779material.wireframe === true780? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin )781: fillPath( _color );782783}784785}786787//788789function drawTriangle( x0, y0, x1, y1, x2, y2 ) {790791_context.beginPath();792_context.moveTo( x0, y0 );793_context.lineTo( x1, y1 );794_context.lineTo( x2, y2 );795_context.closePath();796797}798799function strokePath( color, linewidth, linecap, linejoin ) {800801setLineWidth( linewidth );802setLineCap( linecap );803setLineJoin( linejoin );804setStrokeStyle( color.getStyle() );805806_context.stroke();807808_elemBox.expandByScalar( linewidth * 2 );809810}811812function fillPath( color ) {813814setFillStyle( color.getStyle() );815_context.fill();816817}818819function textureToPattern( texture ) {820821if ( texture.version === 0 ||822texture instanceof THREE.CompressedTexture ||823texture instanceof THREE.DataTexture ) {824825return {826canvas: undefined,827version: texture.version828}829830}831832var image = texture.image;833834var canvas = document.createElement( 'canvas' );835canvas.width = image.width;836canvas.height = image.height;837838var context = canvas.getContext( '2d' );839context.setTransform( 1, 0, 0, - 1, 0, image.height );840context.drawImage( image, 0, 0 );841842var repeatX = texture.wrapS === THREE.RepeatWrapping;843var repeatY = texture.wrapT === THREE.RepeatWrapping;844845var repeat = 'no-repeat';846847if ( repeatX === true && repeatY === true ) {848849repeat = 'repeat';850851} else if ( repeatX === true ) {852853repeat = 'repeat-x';854855} else if ( repeatY === true ) {856857repeat = 'repeat-y';858859}860861return {862canvas: _context.createPattern( canvas, repeat ),863version: texture.version864}865866}867868function patternPath( x0, y0, x1, y1, x2, y2, u0, v0, u1, v1, u2, v2, texture ) {869870var pattern = _patterns[ texture.id ];871872if ( pattern === undefined || pattern.version !== texture.version ) {873874pattern = textureToPattern( texture );875_patterns[ texture.id ] = pattern;876877}878879if ( pattern.canvas !== undefined ) {880881setFillStyle( pattern.canvas );882883} else {884885setFillStyle( 'rgba( 0, 0, 0, 1)' );886_context.fill();887return;888889}890891// http://extremelysatisfactorytotalitarianism.com/blog/?p=2120892893var a, b, c, d, e, f, det, idet,894offsetX = texture.offset.x / texture.repeat.x,895offsetY = texture.offset.y / texture.repeat.y,896width = texture.image.width * texture.repeat.x,897height = texture.image.height * texture.repeat.y;898899u0 = ( u0 + offsetX ) * width;900v0 = ( v0 + offsetY ) * height;901902u1 = ( u1 + offsetX ) * width;903v1 = ( v1 + offsetY ) * height;904905u2 = ( u2 + offsetX ) * width;906v2 = ( v2 + offsetY ) * height;907908x1 -= x0; y1 -= y0;909x2 -= x0; y2 -= y0;910911u1 -= u0; v1 -= v0;912u2 -= u0; v2 -= v0;913914det = u1 * v2 - u2 * v1;915916if ( det === 0 ) return;917918idet = 1 / det;919920a = ( v2 * x1 - v1 * x2 ) * idet;921b = ( v2 * y1 - v1 * y2 ) * idet;922c = ( u1 * x2 - u2 * x1 ) * idet;923d = ( u1 * y2 - u2 * y1 ) * idet;924925e = x0 - a * u0 - c * v0;926f = y0 - b * u0 - d * v0;927928_context.save();929_context.transform( a, b, c, d, e, f );930_context.fill();931_context.restore();932933}934935function clipImage( x0, y0, x1, y1, x2, y2, u0, v0, u1, v1, u2, v2, image ) {936937// http://extremelysatisfactorytotalitarianism.com/blog/?p=2120938939var a, b, c, d, e, f, det, idet,940width = image.width - 1,941height = image.height - 1;942943u0 *= width; v0 *= height;944u1 *= width; v1 *= height;945u2 *= width; v2 *= height;946947x1 -= x0; y1 -= y0;948x2 -= x0; y2 -= y0;949950u1 -= u0; v1 -= v0;951u2 -= u0; v2 -= v0;952953det = u1 * v2 - u2 * v1;954955idet = 1 / det;956957a = ( v2 * x1 - v1 * x2 ) * idet;958b = ( v2 * y1 - v1 * y2 ) * idet;959c = ( u1 * x2 - u2 * x1 ) * idet;960d = ( u1 * y2 - u2 * y1 ) * idet;961962e = x0 - a * u0 - c * v0;963f = y0 - b * u0 - d * v0;964965_context.save();966_context.transform( a, b, c, d, e, f );967_context.clip();968_context.drawImage( image, 0, 0 );969_context.restore();970971}972973// Hide anti-alias gaps974975function expand( v1, v2, pixels ) {976977var x = v2.x - v1.x, y = v2.y - v1.y,978det = x * x + y * y, idet;979980if ( det === 0 ) return;981982idet = pixels / Math.sqrt( det );983984x *= idet; y *= idet;985986v2.x += x; v2.y += y;987v1.x -= x; v1.y -= y;988989}990991// Context cached methods.992993function setOpacity( value ) {994995if ( _contextGlobalAlpha !== value ) {996997_context.globalAlpha = value;998_contextGlobalAlpha = value;9991000}10011002}10031004function setBlending( value ) {10051006if ( _contextGlobalCompositeOperation !== value ) {10071008if ( value === THREE.NormalBlending ) {10091010_context.globalCompositeOperation = 'source-over';10111012} else if ( value === THREE.AdditiveBlending ) {10131014_context.globalCompositeOperation = 'lighter';10151016} else if ( value === THREE.SubtractiveBlending ) {10171018_context.globalCompositeOperation = 'darker';10191020}10211022_contextGlobalCompositeOperation = value;10231024}10251026}10271028function setLineWidth( value ) {10291030if ( _contextLineWidth !== value ) {10311032_context.lineWidth = value;1033_contextLineWidth = value;10341035}10361037}10381039function setLineCap( value ) {10401041// "butt", "round", "square"10421043if ( _contextLineCap !== value ) {10441045_context.lineCap = value;1046_contextLineCap = value;10471048}10491050}10511052function setLineJoin( value ) {10531054// "round", "bevel", "miter"10551056if ( _contextLineJoin !== value ) {10571058_context.lineJoin = value;1059_contextLineJoin = value;10601061}10621063}10641065function setStrokeStyle( value ) {10661067if ( _contextStrokeStyle !== value ) {10681069_context.strokeStyle = value;1070_contextStrokeStyle = value;10711072}10731074}10751076function setFillStyle( value ) {10771078if ( _contextFillStyle !== value ) {10791080_context.fillStyle = value;1081_contextFillStyle = value;10821083}10841085}10861087function setLineDash( value ) {10881089if ( _contextLineDash.length !== value.length ) {10901091_context.setLineDash( value );1092_contextLineDash = value;10931094}10951096}10971098};109911001101