1/** 2 * @author mrdoob / http://mrdoob.com/ 3 */ 4 5THREEW.SpriteCanvasMaterial = function ( parameters ) { 6 7 THREEW.Material.call( this ); 8 9 this.type = 'SpriteCanvasMaterial'; 10 11 this.color = new THREEW.Color( 0xffffff ); 12 this.program = function ( context, color ) {}; 13 14 this.setValues( parameters ); 15 16}; 17 18THREEW.SpriteCanvasMaterial.prototype = Object.create( THREEW.Material.prototype ); 19THREEW.SpriteCanvasMaterial.prototype.constructor = THREEW.SpriteCanvasMaterial; 20 21THREEW.SpriteCanvasMaterial.prototype.clone = function () { 22 23 var material = new THREEW.SpriteCanvasMaterial(); 24 25 material.copy( this ); 26 material.color.copy( this.color ); 27 material.program = this.program; 28 29 return material; 30 31}; 32 33// 34 35THREEW.CanvasRenderer = function ( parameters ) { 36 37 console.log( 'THREEW.CanvasRenderer', THREEW.REVISION ); 38 39 parameters = parameters || {}; 40 41 var _this = this, 42 _renderData, _elements, _lights, 43 _projector = new THREEW.Projector(), 44 45 _canvas = parameters.canvas !== undefined 46 ? parameters.canvas 47 : document.createElement( 'canvas' ), 48 49 _canvasWidth = _canvas.width, 50 _canvasHeight = _canvas.height, 51 _canvasWidthHalf = Math.floor( _canvasWidth / 2 ), 52 _canvasHeightHalf = Math.floor( _canvasHeight / 2 ), 53 54 _viewportX = 0, 55 _viewportY = 0, 56 _viewportWidth = _canvasWidth, 57 _viewportHeight = _canvasHeight, 58 59 _pixelRatio = 1, 60 61 _context = _canvas.getContext( '2d', { 62 alpha: parameters.alpha === true 63 } ), 64 65 _clearColor = new THREEW.Color( 0x000000 ), 66 _clearAlpha = parameters.alpha === true ? 0 : 1, 67 68 _contextGlobalAlpha = 1, 69 _contextGlobalCompositeOperation = 0, 70 _contextStrokeStyle = null, 71 _contextFillStyle = null, 72 _contextLineWidth = null, 73 _contextLineCap = null, 74 _contextLineJoin = null, 75 _contextLineDash = [], 76 77 _camera, 78 79 _v1, _v2, _v3, _v4, 80 _v5 = new THREEW.RenderableVertex(), 81 _v6 = new THREEW.RenderableVertex(), 82 83 _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, 84 _v4x, _v4y, _v5x, _v5y, _v6x, _v6y, 85 86 _color = new THREEW.Color(), 87 _color1 = new THREEW.Color(), 88 _color2 = new THREEW.Color(), 89 _color3 = new THREEW.Color(), 90 _color4 = new THREEW.Color(), 91 92 _diffuseColor = new THREEW.Color(), 93 _emissiveColor = new THREEW.Color(), 94 95 _lightColor = new THREEW.Color(), 96 97 _patterns = {}, 98 99 _image, _uvs, 100 _uv1x, _uv1y, _uv2x, _uv2y, _uv3x, _uv3y, 101 102 _clipBox = new THREEW.Box2(), 103 _clearBox = new THREEW.Box2(), 104 _elemBox = new THREEW.Box2(), 105 106 _ambientLight = new THREEW.Color(), 107 _directionalLights = new THREEW.Color(), 108 _pointLights = new THREEW.Color(), 109 110 _vector3 = new THREEW.Vector3(), // Needed for PointLight 111 _centroid = new THREEW.Vector3(), 112 _normal = new THREEW.Vector3(), 113 _normalViewMatrix = new THREEW.Matrix3(); 114 115 /* TODO 116 _canvas.mozImageSmoothingEnabled = false; 117 _canvas.webkitImageSmoothingEnabled = false; 118 _canvas.msImageSmoothingEnabled = false; 119 _canvas.imageSmoothingEnabled = false; 120 */ 121 122 // dash+gap fallbacks for Firefox and everything else 123 124 if ( _context.setLineDash === undefined ) { 125 126 _context.setLineDash = function () {}; 127 128 } 129 130 this.domElement = _canvas; 131 132 this.autoClear = true; 133 this.sortObjects = true; 134 this.sortElements = true; 135 136 this.info = { 137 138 render: { 139 140 vertices: 0, 141 faces: 0 142 143 } 144 145 }; 146 147 // WebGLRenderer compatibility 148 149 this.supportsVertexTextures = function () {}; 150 this.setFaceCulling = function () {}; 151 152 // API 153 154 this.getContext = function () { 155 156 return _context; 157 158 }; 159 160 this.getContextAttributes = function () { 161 162 return _context.getContextAttributes(); 163 164 }; 165 166 this.getPixelRatio = function () { 167 168 return _pixelRatio; 169 170 }; 171 172 this.setPixelRatio = function ( value ) { 173 174 if ( value !== undefined ) _pixelRatio = value; 175 176 }; 177 178 this.setSize = function ( width, height, updateStyle ) { 179 180 _canvasWidth = width * _pixelRatio; 181 _canvasHeight = height * _pixelRatio; 182 183 _canvas.width = _canvasWidth; 184 _canvas.height = _canvasHeight; 185 186 _canvasWidthHalf = Math.floor( _canvasWidth / 2 ); 187 _canvasHeightHalf = Math.floor( _canvasHeight / 2 ); 188 189 if ( updateStyle !== false ) { 190 191 _canvas.style.width = width + 'px'; 192 _canvas.style.height = height + 'px'; 193 194 } 195 196 _clipBox.min.set( - _canvasWidthHalf, - _canvasHeightHalf ); 197 _clipBox.max.set( _canvasWidthHalf, _canvasHeightHalf ); 198 199 _clearBox.min.set( - _canvasWidthHalf, - _canvasHeightHalf ); 200 _clearBox.max.set( _canvasWidthHalf, _canvasHeightHalf ); 201 202 _contextGlobalAlpha = 1; 203 _contextGlobalCompositeOperation = 0; 204 _contextStrokeStyle = null; 205 _contextFillStyle = null; 206 _contextLineWidth = null; 207 _contextLineCap = null; 208 _contextLineJoin = null; 209 210 this.setViewport( 0, 0, width, height ); 211 212 }; 213 214 this.setViewport = function ( x, y, width, height ) { 215 216 _viewportX = x * _pixelRatio; 217 _viewportY = y * _pixelRatio; 218 219 _viewportWidth = width * _pixelRatio;
220 _viewportHeight = height * _pixelRatio; 221 222 }; 223 224 this.setScissor = function () {}; 225 this.setScissorTest = function () {}; 226 227 this.setClearColor = function ( color, alpha ) { 228 229 _clearColor.set( color ); 230 _clearAlpha = alpha !== undefined ? alpha : 1; 231 232 _clearBox.min.set( - _canvasWidthHalf, - _canvasHeightHalf ); 233 _clearBox.max.set( _canvasWidthHalf, _canvasHeightHalf ); 234 235 }; 236 237 this.setClearColorHex = function ( hex, alpha ) { 238 239 console.warn( 'THREEW.CanvasRenderer: .setClearColorHex() is being removed. Use .setClearColor() instead.' ); 240 this.setClearColor( hex, alpha ); 241 242 }; 243 244 this.getClearColor = function () { 245 246 return _clearColor; 247 248 }; 249 250 this.getClearAlpha = function () { 251 252 return _clearAlpha; 253 254 }; 255 256 this.getMaxAnisotropy = function () { 257 258 return 0; 259 260 }; 261 262 this.clear = function () { 263 264 if ( _clearBox.isEmpty() === false ) { 265 266 _clearBox.intersect( _clipBox ); 267 _clearBox.expandByScalar( 2 ); 268 269 _clearBox.min.x = _clearBox.min.x + _canvasWidthHalf; 270 _clearBox.min.y = - _clearBox.min.y + _canvasHeightHalf; // higher y value ! 271 _clearBox.max.x = _clearBox.max.x + _canvasWidthHalf; 272 _clearBox.max.y = - _clearBox.max.y + _canvasHeightHalf; // lower y value ! 273 274 if ( _clearAlpha < 1 ) { 275 276 _context.clearRect( 277 _clearBox.min.x | 0, 278 _clearBox.max.y | 0, 279 ( _clearBox.max.x - _clearBox.min.x ) | 0, 280 ( _clearBox.min.y - _clearBox.max.y ) | 0 281 ); 282 283 } 284
285 if ( _clearAlpha > 0 ) { 286 287 setBlending( THREEW.NormalBlending ); 288 setOpacity( 1 ); 289 290 setFillStyle( 'rgba(' + Math.floor( _clearColor.r * 255 ) + ',' + Math.floor( _clearColor.g * 255 ) + ',' + Math.floor( _clearColor.b * 255 ) + ',' + _clearAlpha + ')' ); 291 292 _context.fillRect( 293 _clearBox.min.x | 0, 294 _clearBox.max.y | 0, 295 ( _clearBox.max.x - _clearBox.min.x ) | 0, 296 ( _clearBox.min.y - _clearBox.max.y ) | 0 297 ); 298 299 } 300 301 _clearBox.makeEmpty(); 302 303 } 304 305 }; 306 307 // compatibility 308 309 this.clearColor = function () {}; 310 this.clearDepth = function () {}; 311 this.clearStencil = function () {}; 312 313 this.render = function ( scene, camera ) { 314 315 if ( camera instanceof THREEW.Camera === false ) { 316 317 console.error( 'THREEW.CanvasRenderer.render: camera is not an instance of THREEW.Camera.' ); 318 return; 319 320 } 321 322 if ( this.autoClear === true ) this.clear(); 323 324 _this.info.render.vertices = 0; 325 _this.info.render.faces = 0; 326 327 _context.setTransform( _viewportWidth / _canvasWidth, 0, 0, - _viewportHeight / _canvasHeight, _viewportX, _canvasHeight - _viewportY ); 328 _context.translate( _canvasWidthHalf, _canvasHeightHalf ); 329 330 _renderData = _projector.projectScene( scene, camera, this.sortObjects, this.sortElements ); 331 _elements = _renderData.elements; 332 _lights = _renderData.lights; 333 _camera = camera; 334 335 _normalViewMatrix.getNormalMatrix( camera.matrixWorldInverse ); 336 337 /* DEBUG 338 setFillStyle( 'rgba( 0, 255, 255, 0.5 )' ); 339 _context.fillRect( _clipBox.min.x, _clipBox.min.y, _clipBox.max.x - _clipBox.min.x, _clipBox.max.y - _clipBox.min.y ); 340 */ 341 342 calculateLights(); 343 344 for ( var e = 0, el = _elements.length; e < el; e ++ ) { 345 346 var element = _elements[ e ]; 347 348 var material = element.material; 349 350 if ( material === undefined || material.opacity === 0 ) continue; 351 352 _elemBox.makeEmpty(); 353 354 if ( element instanceof THREEW.RenderableSprite ) { 355 356 _v1 = element; 357 _v1.x *= _canvasWidthHalf; _v1.y *= _canvasHeightHalf; 358 359 renderSprite( _v1, element, material ); 360 361 } else if ( element instanceof THREEW.RenderableLine ) { 362 363 _v1 = element.v1; _v2 = element.v2; 364 365 _v1.positionScreen.x *= _canvasWidthHalf; _v1.positionScreen.y *= _canvasHeightHalf; 366 _v2.positionScreen.x *= _canvasWidthHalf; _v2.positionScreen.y *= _canvasHeightHalf; 367 368 _elemBox.setFromPoints( [ 369 _v1.positionScreen, 370 _v2.positionScreen 371 ] ); 372 373 if ( _clipBox.intersectsBox( _elemBox ) === true ) { 374 375 renderLine( _v1, _v2, element, material ); 376 377 } 378 379 } else if ( element instanceof THREEW.RenderableFace ) { 380 381 _v1 = element.v1; _v2 = element.v2; _v3 = element.v3; 382 383 if ( _v1.positionScreen.z < - 1 || _v1.positionScreen.z > 1 ) continue; 384 if ( _v2.positionScreen.z < - 1 || _v2.positionScreen.z > 1 ) continue; 385 if ( _v3.positionScreen.z < - 1 || _v3.positionScreen.z > 1 ) continue; 386 387 _v1.positionScreen.x *= _canvasWidthHalf; _v1.positionScreen.y *= _canvasHeightHalf; 388 _v2.positionScreen.x *= _canvasWidthHalf; _v2.positionScreen.y *= _canvasHeightHalf; 389 _v3.positionScreen.x *= _canvasWidthHalf; _v3.positionScreen.y *= _canvasHeightHalf; 390 391 if ( material.overdraw > 0 ) { 392 393 expand( _v1.positionScreen, _v2.positionScreen, material.overdraw ); 394 expand( _v2.positionScreen, _v3.positionScreen, material.overdraw ); 395 expand( _v3.positionScreen, _v1.positionScreen, material.overdraw ); 396 397 } 398 399 _elemBox.setFromPoints( [ 400 _v1.positionScreen, 401 _v2.positionScreen, 402 _v3.positionScreen 403 ] ); 404 405 if ( _clipBox.intersectsBox( _elemBox ) === true ) { 406 407 renderFace3( _v1, _v2, _v3, 0, 1, 2, element, material ); 408 409 } 410 411 } 412 413 /* DEBUG 414 setLineWidth( 1 ); 415 setStrokeStyle( 'rgba( 0, 255, 0, 0.5 )' ); 416 _context.strokeRect( _elemBox.min.x, _elemBox.min.y, _elemBox.max.x - _elemBox.min.x, _elemBox.max.y - _elemBox.min.y ); 417 */ 418 419 _clearBox.union( _elemBox ); 420 421 } 422 423 /* DEBUG 424 setLineWidth( 1 ); 425 setStrokeStyle( 'rgba( 255, 0, 0, 0.5 )' ); 426 _context.strokeRect( _clearBox.min.x, _clearBox.min.y, _clearBox.max.x - _clearBox.min.x, _clearBox.max.y - _clearBox.min.y ); 427 */ 428 429 _context.setTransform( 1, 0, 0, 1, 0, 0 ); 430 431 }; 432 433 // 434 435 function calculateLights() { 436 437 _ambientLight.setRGB( 0, 0, 0 ); 438 _directionalLights.setRGB( 0, 0, 0 ); 439 _pointLights.setRGB( 0, 0, 0 ); 440 441 for ( var l = 0, ll = _lights.length; l < ll;
441 l ++ ) { 442 443 var light = _lights[ l ]; 444 var lightColor = light.color; 445 446 if ( light instanceof THREEW.AmbientLight ) { 447 448 _ambientLight.add( lightColor ); 449 450 } else if ( light instanceof THREEW.DirectionalLight ) { 451 452 // for sprites 453 454 _directionalLights.add( lightColor ); 455 456 } else if ( light instanceof THREEW.PointLight ) { 457 458 // for sprites 459 460 _pointLights.add( lightColor ); 461 462 } 463 464 } 465 466 } 467 468 function calculateLight( position, normal, color ) { 469 470 for ( var l = 0, ll = _lights.length; l < ll; l ++ ) { 471 472 var light = _lights[ l ]; 473 474 _lightColor.copy( light.color ); 475 476 if ( light instanceof THREEW.DirectionalLight ) { 477 478 var lightPosition = _vector3.setFromMatrixPosition( light.matrixWorld ).normalize(); 479 480 var amount = normal.dot( lightPosition ); 481 482 if ( amount <= 0 ) continue; 483 484 amount *= light.intensity; 485 486 color.add( _lightColor.multiplyScalar( amount ) ); 487 488 } else if ( light instanceof THREEW.PointLight ) { 489 490 var lightPosition = _vector3.setFromMatrixPosition( light.matrixWorld ); 491 492 var amount = normal.dot( _vector3.subVectors( lightPosition, position ).normalize() ); 493 494 if ( amount <= 0 ) continue; 495 496 amount *= light.distance == 0 ? 1 : 1 - Math.min( position.distanceTo( lightPosition ) / light.distance, 1 ); 497 498 if ( amount == 0 ) continue; 499 500 amount *= light.intensity; 501 502 color.add( _lightColor.multiplyScalar( amount ) ); 503 504 } 505 506 } 507 508 } 509
510 function renderSprite( v1, element, material ) { 511 512 setOpacity( material.opacity ); 513 setBlending( material.blending ); 514 515 var scaleX = element.scale.x * _canvasWidthHalf; 516 var scaleY = element.scale.y * _canvasHeightHalf; 517 518 var dist = 0.5 * Math.sqrt( scaleX * scaleX + scaleY * scaleY ); // allow for rotated sprite 519 _elemBox.min.set( v1.x - dist, v1.y - dist ); 520 _elemBox.max.set( v1.x + dist, v1.y + dist ); 521 522 if ( material instanceof THREEW.SpriteMaterial ) { 523 524 var texture = material.map; 525 526 if ( texture !== null ) { 527 528 var pattern = _patterns[ texture.id ]; 529 530 if ( pattern === undefined || pattern.version !== texture.version ) { 531 532 pattern = textureToPattern( texture ); 533 _patterns[ texture.id ] = pattern; 534 535 } 536 537 if ( pattern.canvas !== undefined ) { 538 539 setFillStyle( pattern.canvas ); 540 541 var bitmap = texture.image; 542 543 var ox = bitmap.width * texture.offset.x; 544 var oy = bitmap.height * texture.offset.y; 545 546 var sx = bitmap.width * texture.repeat.x; 547 var sy = bitmap.height * texture.repeat.y; 548 549 var cx = scaleX / sx; 550 var cy = scaleY / sy; 551 552 _context.save(); 553 _context.translate( v1.x, v1.y ); 554 if ( material.rotation !== 0 ) _context.rotate( material.rotation ); 555 _context.translate( - scaleX / 2, - scaleY / 2 ); 556 _context.scale( cx, cy ); 557 _context.translate( - ox, - oy ); 558 _context.fillRect( ox, oy, sx, sy ); 559 _context.restore(); 560 561 } 562 563 } else { 564 565 // no texture 566 567 setFillStyle( material.color.getStyle() ); 568 569 _context.save(); 570 _context.translate( v1.x, v1.y ); 571 if ( material.rotation !== 0 ) _context.rotate( material.rotation ); 572 _context.scale( scaleX, - scaleY ); 573 _context.fillRect( - 0.5, - 0.5, 1, 1 ); 574 _context.restore(); 575 576 } 577 578 } else if ( material instanceof THREEW.SpriteCanvasMaterial ) { 579 580 setStrokeStyle( material.color.getStyle() ); 581 setFillStyle( material.color.getStyle() ); 582 583 _context.save(); 584 _context.translate( v1.x, v1.y ); 585 if ( material.rotation !== 0 ) _context.rotate( material.rotation ); 586 _context.scale( scaleX, scaleY ); 587 588 material.program( _context ); 589 590 _context.restore(); 591 592 } 593 594 /* DEBUG 595 setStrokeStyle( 'rgb(255,255,0)' ); 596 _context.beginPath(); 597 _context.moveTo( v1.x - 10, v1.y ); 598 _context.lineTo( v1.x + 10, v1.y ); 599 _context.moveTo( v1.x, v1.y - 10 ); 600 _context.lineTo( v1.x, v1.y + 10 ); 601 _context.stroke(); 602 */ 603 604 } 605 606 function renderLine( v1, v2, element, material ) { 607 608 setOpacity( material.opacity ); 609 setBlending( material.blending ); 610 611 _context.beginPath(); 612 _context.moveTo( v1.positionScreen.x, v1.positionScreen.y ); 613 _context.lineTo( v2.positionScreen.x, v2.positionScreen.y ); 614 615 if ( material instanceof THREEW.LineBasicMaterial ) { 616 617 setLineWidth( material.linewidth ); 618 setLineCap( material.linecap ); 619 setLineJoin( material.linejoin ); 620 621 if ( material.vertexColors !== THREEW.VertexColors ) { 622 623 setStrokeStyle( material.color.getStyle() ); 624 625 } else { 626 627 var colorStyle1 = element.vertexColors[ 0 ].getStyle(); 628 var colorStyle2 = element.vertexColors[ 1 ].getStyle(); 629 630 if ( colorStyle1 === colorStyle2 ) { 631 632 setStrokeStyle( colorStyle1 ); 633 634 } else { 635 636 try { 637 638 var grad = _context.createLinearGradient( 639 v1.positionScreen.x, 640 v1.positionScreen.y, 641 v2.positionScreen.x, 642 v2.positionScreen.y 643 ); 644 grad.addColorStop( 0, colorStyle1 ); 645 grad.addColorStop( 1, colorStyle2 ); 646 647 } catch ( exception ) { 648 649 grad = colorStyle1; 650 651 } 652 653 setStrokeStyle( grad ); 654 655 } 656 657 } 658 659 _context.stroke(); 660 _elemBox.expandByScalar( material.linewidth * 2 ); 661 662 } else if ( material instanceof THREEW.LineDashedMaterial ) { 663 664 setLineWidth( material.linewidth ); 665 setLineCap( material.linecap ); 666 setLineJoin( material.linejoin ); 667 setStrokeStyle( material.color.getStyle() ); 668 setLineDash( [ material.dashSize, material.gapSize ] ); 669 670 _context.stroke(); 671 672 _elemBox.expandByScalar( material.linewidth * 2 ); 673 674 setLineDash( [] ); 675 676 } 677 678 } 679 680 function renderFace3( v1, v2, v3, uv1, uv2, uv3, element, material ) { 681 682 _this.info.render.vertices += 3; 683 _this.info.render.faces ++; 684 685 setOpacity( material.opacity ); 686 setBlending( material.blending ); 687 688 _v1x = v1.positionScreen.x; _v1y = v1.positionScreen.y; 689 _v2x = v2.positionScreen.x; _v2y = v2.positionScreen.y; 690 _v3x = v3.positionScreen.x; _v3y = v3.positionScreen.y; 691 692 drawTriangle( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y ); 693 694 if ( ( material instanceof THREEW.MeshLambertMaterial || material instanceof THREEW.MeshPhongMaterial ) && material.map === null ) { 695 696 _diffuseColor.copy( material.color ); 697 _emissiveColor.copy( material.emissive ); 698 699 if ( material.vertexColors === THREEW.FaceColors ) { 700 701 _diffuseColor.multiply( element.color ); 702 703 } 704 705 _color.copy( _ambientLight ); 706 707 _centroid.copy( v1.positionWorld ).add( v2.positionWorld ).add( v3.positionWorld ).divideScalar( 3 ); 708 709 calculateLight( _centroid, element.normalModel, _color ); 710 711 _color.multiply( _diffuseColor ).add( _emissiveColor ); 712 713 714 material.wireframe === true 715 ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin ) 716 : fillPath( _color ); 717 718 } else if ( material instanceof THREEW.MeshBasicMaterial || 719 material instanceof THREEW.MeshLambertMaterial || 720 material instanceof THREEW.MeshPhongMaterial ) { 721 722 if ( material.map !== null ) { 723 724 var mapping = material.map.mapping; 725 726 if ( mapping === THREEW.UVMapping ) { 727 728 _uvs = element.uvs; 729 patternPath( _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 ); 730 731 } 732 733 } else if ( material.envMap !== null ) { 734 735 if ( material.envMap.mapping === THREEW.SphericalReflectionMapping ) { 736 737 _normal.copy( element.vertexNormalsModel[ uv1 ] ).applyMatrix3( _normalViewMatrix ); 738 _uv1x = 0.5 * _normal.x + 0.5; 739 _uv1y = 0.5 * _normal.y + 0.5; 740 741 _normal.copy( element.vertexNormalsModel[ uv2 ] ).applyMatrix3( _normalViewMatrix ); 742 _uv2x = 0.5 * _normal.x + 0.5; 743 _uv2y = 0.5 * _normal.y + 0.5; 744 745 _normal.copy( element.vertexNormalsModel[ uv3 ] ).applyMatrix3( _normalViewMatrix ); 746 _uv3x = 0.5 * _normal.x + 0.5; 747 _uv3y = 0.5 * _normal.y + 0.5; 748 749 patternPath( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _uv1x, _uv1y, _uv2x, _uv2y, _uv3x, _uv3y, material.envMap ); 750 751 } 752 753 } else { 754 755 _color.copy( material.color ); 756 757 if ( material.vertexColors === THREEW.FaceColors ) { 758 759 _color.multiply( element.color ); 760 761 } 762 763 material.wireframe === true 764 ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin ) 765 : fillPath( _color ); 766 767 } 768 769 } else if ( material instanceof THREEW.MeshNormalMaterial ) { 770 771 _normal.copy( element.normalModel ).applyMatrix3( _normalViewMatrix ); 772 773 _color.setRGB( _normal.x, _normal.y, _normal.z ).multiplyScalar( 0.5 ).addScalar( 0.5 ); 774 775 material.wireframe === true 776 ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin ) 777 : fillPath( _color ); 778 779 } else { 780 781 _color.setRGB( 1, 1, 1 ); 782 783 material.wireframe === true 784 ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin ) 785 : fillPath( _color ); 786 787 } 788 789 } 790 791 // 792 793 function drawTriangle( x0, y0, x1, y1, x2, y2 ) { 794 795 _context.beginPath(); 796 _context.moveTo( x0, y0 ); 797 _context.lineTo( x1, y1 ); 798 _context.lineTo( x2, y2 ); 799 _context.closePath(); 800 801 } 802 803 function strokePath( color, linewidth, linecap, linejoin ) { 804 805 setLineWidth( linewidth ); 806 setLineCap( linecap ); 807 setLineJoin( linejoin ); 808 setStrokeStyle( color.getStyle() ); 809 810 _context.stroke(); 811
812 _elemBox.expandByScalar( linewidth * 2 ); 813 814 } 815 816 function fillPath( color ) { 817 818 setFillStyle( color.getStyle() ); 819 _context.fill(); 820 821 } 822 823 function textureToPattern( texture ) { 824 825 if ( texture.version === 0 || 826 texture instanceof THREEW.CompressedTexture || 827 texture instanceof THREEW.DataTexture ) { 828 829 return { 830 canvas: undefined, 831 version: texture.version 832 }; 833 834 } 835 836 var image = texture.image; 837 838 if ( image.complete === false ) { 839 840 return { 841 canvas: undefined, 842 version: 0 843 }; 844 845 } 846 847 var canvas = document.createElement( 'canvas' ); 848 canvas.width = image.width; 849 canvas.height = image.height; 850 851 var context = canvas.getContext( '2d' ); 852 context.setTransform( 1, 0, 0, - 1, 0, image.height ); 853 context.drawImage( image, 0, 0 ); 854 855 var repeatX = texture.wrapS === THREEW.RepeatWrapping; 856 var repeatY = texture.wrapT === THREEW.RepeatWrapping; 857 858 var repeat = 'no-repeat'; 859 860 if ( repeatX === true && repeatY === true ) { 861 862 repeat = 'repeat'; 863 864 } else if ( repeatX === true ) { 865 866 repeat = 'repeat-x'; 867 868 } else if ( repeatY === true ) { 869 870 repeat = 'repeat-y'; 871 872 } 873 874 var pattern = _context.createPattern( canvas, repeat ); 875 876 if ( texture.onUpdate ) texture.onUpdate( texture ); 877 878 return { 879 canvas: pattern, 880 version: texture.version 881 }; 882 883 } 884 885 function patternPath( x0, y0, x1, y1, x2, y2, u0, v0, u1, v1, u2, v2, texture ) { 886 887 var pattern = _patterns[ texture.id ]; 888 889 if ( pattern === undefined || pattern.version !== texture.version ) { 890 891 pattern = textureToPattern( texture ); 892 _patterns[ texture.id ] = pattern; 893 894 } 895 896 if ( pattern.canvas !== undefined ) { 897 898 setFillStyle( pattern.canvas ); 899 900 } else { 901 902 setFillStyle( 'rgba( 0, 0, 0, 1)' ); 903 _context.fill(); 904 return; 905 906 } 907 908 // http://extremelysatisfactorytotalitarianism.com/blog/?p=2120 909 910 var a, b, c, d, e, f, det, idet, 911 offsetX = texture.offset.x / texture.repeat.x, 912 offsetY = texture.offset.y / texture.repeat.y, 913 width = texture.image.width * texture.repeat.x, 914 height = texture.image.height * texture.repeat.y; 915 916 u0 = ( u0 + offsetX ) * width; 917 v0 = ( v0 + offsetY ) * height; 918 919 u1 = ( u1 + offsetX ) * width; 920 v1 = ( v1 + offsetY ) * height; 921 922 u2 = ( u2 + offsetX ) * width; 923 v2 = ( v2 + offsetY ) * height; 924 925 x1 -= x0; y1 -= y0; 926 x2 -= x0; y2 -= y0; 927 928 u1 -= u0; v1 -= v0; 929 u2 -= u0; v2 -= v0; 930 931 det = u1 * v2 - u2 * v1; 932 933 if ( det === 0 ) return; 934 935 idet = 1 / det; 936 937 a = ( v2 * x1 - v1 * x2 ) * idet; 938 b = ( v2 * y1 - v1 * y2 ) * idet; 939 c = ( u1 * x2 - u2 * x1 ) * idet; 940 d = ( u1 * y2 - u2 * y1 ) * idet; 941 942 e = x0 - a * u0 - c * v0; 943 f = y0 - b * u0 - d * v0; 944 945 _context.save(); 946 _context.transform( a, b, c, d, e, f ); 947 _context.fill(); 948 _context.restore(); 949 950 } 951 952 function clipImage( x0, y0, x1, y1, x2, y2, u0, v0, u1, v1, u2, v2, image ) { 953 954 // http://extremelysatisfactorytotalitarianism.com/blog/?p=2120 955 956 var a, b, c, d, e, f, det, idet, 957 width = image.width - 1, 958 height = image.height - 1; 959 960 u0 *= width; v0 *= height; 961 u1 *= width; v1 *= height; 962 u2 *= width; v2 *= height; 963 964 x1 -= x0; y1 -= y0; 965 x2 -= x0; y2 -= y0; 966 967 u1 -= u0; v1 -= v0; 968 u2 -= u0; v2 -= v0; 969 970 det = u1 * v2 - u2 * v1; 971 972 idet = 1 / det; 973 974 a = ( v2 * x1 - v1 * x2 ) * idet; 975 b = ( v2 * y1 - v1 * y2 ) * idet; 976 c = ( u1 * x2 - u2 * x1 ) * idet; 977 d = ( u1 * y2 - u2 * y1 ) * idet; 978 979 e = x0 - a * u0 - c * v0; 980 f = y0 - b * u0 - d * v0; 981 982 _context.save(); 983 _context.transform( a, b, c, d, e, f ); 984 _context.clip(); 985 _context.drawImage( image, 0, 0 ); 986 _context.restore(); 987 988 } 989 990 // Hide anti-alias gaps 991 992 function expand( v1, v2, pixels ) { 993 994 var x = v2.x - v1.x, y = v2.y - v1.y, 995 det = x * x + y * y, idet; 996 997 if ( det === 0 ) return; 998 999 idet = pixels / Math.sqrt( det ); 1000 1001 x *= idet; y *= idet; 1002 1003 v2.x += x; v2.y += y; 1004 v1.x -= x; v1.y -= y; 1005 1006 } 1007 1008 // Context cached methods. 1009 1010 function setOpacity( value ) { 1011 1012 if ( _contextGlobalAlpha !== value ) { 1013 1014 _context.globalAlpha = value; 1015 _contextGlobalAlpha = value; 1016 1017 } 1018 1019 } 1020 1021 function setBlending( value ) { 1022 1023 if ( _contextGlobalCompositeOperation !== value ) { 1024 1025 if ( value === THREEW.NormalBlending ) { 1026 1027 _context.globalCompositeOperation = 'source-over'; 1028 1029 } else if ( value === THREEW.AdditiveBlending ) { 1030 1031 _context.globalCompositeOperation = 'lighter'; 1032 1033 } else if ( value === THREEW.SubtractiveBlending ) { 1034 1035 _context.globalCompositeOperation = 'darker'; 1036 1037 } else if ( value === THREEW.MultiplyBlending ) { 1038 1039 _context.globalCompositeOperation = 'multiply'; 1040 1041 } 1042 1043 _contextGlobalCompositeOperation = value; 1044 1045 } 1046 1047 } 1048 1049 function setLineWidth( value ) { 1050 1051 if ( _contextLineWidth !== value ) { 1052 1053 _context.lineWidth = value; 1054 _contextLineWidth = value; 1055 1056 } 1057 1058 } 1059 1060 function setLineCap( value ) { 1061 1062 // "butt", "round", "square" 1063 1064 if ( _contextLineCap !== value ) { 1065 1066 _context.lineCap = value; 1067 _contextLineCap = value; 1068 1069 } 1070 1071 } 1072 1073 function setLineJoin( value ) { 1074 1075 // "round", "bevel", "miter" 1076 1077 if ( _contextLineJoin !== value ) { 1078 1079 _context.lineJoin = value; 1080 _contextLineJoin = value; 1081 1082 } 1083 1084 } 1085 1086 function setStrokeStyle( value ) { 1087 1088 if ( _contextStrokeStyle !== value ) { 1089 1090 _context.strokeStyle = value; 1091 _contextStrokeStyle = value; 1092 1093 } 1094 1095 } 1096 1097 function setFillStyle( value ) { 1098 1099 if ( _contextFillStyle !== value ) { 1100 1101 _context.fillStyle = value; 1102 _contextFillStyle = value; 1103 1104 } 1105 1106 } 1107 1108 function setLineDash( value ) { 1109 1110 if ( _contextLineDash.length !== value.length ) { 1111 1112 _context.setLineDash( value ); 1113 _contextLineDash = value; 1114 1115 } 1116 1117 } 1118 1119};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.