1 /**
2 * @author mrdoob / http://mrdoob.com/
3 */
4
5 /**@constructor*/
6 THREE.CanvasRenderer = function ( parameters ) {
7
8 console.log( 'THREE.CanvasRenderer', THREE.REVISION );
9
10 parameters = parameters || {};
11
12 var _this = this,
13 _renderData, _elements, _lights,
14 _projector = new THREE.Projector(),
15
16 _canvas = parameters.canvas !== undefined ? parameters.canvas : document.createElement( 'canvas' ),
17
18 _canvasWidth, _canvasHeight, _canvasWidthHalf, _canvasHeightHalf,
19 _context = _canvas.getContext( '2d' ),
20
21 _clearColor = new THREE.Color( 0x000000 ),
22 _clearOpacity = 0,
23
24 _contextGlobalAlpha = 1,
25 _contextGlobalCompositeOperation = 0,
26 _contextStrokeStyle = null,
27 _contextFillStyle = null,
28 _contextLineWidth = null,
29 _contextLineCap = null,
30 _contextLineJoin = null,
31
32 _v1, _v2, _v3, _v4,
33 _v5 = new THREE.RenderableVertex(),
34 _v6 = new THREE.RenderableVertex(),
35
36 _v1x, _v1y, _v2x, _v2y, _v3x, _v3y,
37 _v4x, _v4y, _v5x, _v5y, _v6x, _v6y,
38
39 _color = new THREE.Color(),
40 _color1 = new THREE.Color(),
41 _color2 = new THREE.Color(),
42 _color3 = new THREE.Color(),
43 _color4 = new THREE.Color(),
44
45 _diffuseColor = new THREE.Color(),
46 _emissiveColor = new THREE.Color(),
47
48 _patterns = {}, _imagedatas = {},
49
50 _near, _far,
51
52 _image, _uvs,
53 _uv1x, _uv1y, _uv2x, _uv2y, _uv3x, _uv3y,
54
55 _clipRect = new THREE.Rectangle(),
56 _clearRect = new THREE.Rectangle(),
57 _bboxRect = new THREE.Rectangle(),
58
59 _enableLighting = false,
60 _ambientLight = new THREE.Color(),
61 _directionalLights = new THREE.Color(),
62 _pointLights = new THREE.Color(),
63
64 _pi2 = Math.PI * 2,
65 _vector3 = new THREE.Vector3(), // Needed for PointLight
66
67 _pixelMap, _pixelMapContext, _pixelMapImage, _pixelMapData,
68 _gradientMap, _gradientMapContext, _gradientMapQuality = 16;
69
70 _pixelMap = document.createElement( 'canvas' );
71 _pixelMap.width = _pixelMap.height = 2;
72
73 _pixelMapContext = _pixelMap.getContext( '2d' );
74 _pixelMapContext.fillStyle = 'rgba(0,0,0,1)';
75 _pixelMapContext.fillRect( 0, 0, 2, 2 );
76
77 _pixelMapImage = _pixelMapContext.getImageData( 0, 0, 2, 2 );
78 _pixelMapData = _pixelMapImage.data;
79
80 _gradientMap = document.createElement( 'canvas' );
81 _gradientMap.width = _gradientMap.height = _gradientMapQuality;
82
83 _gradientMapContext = _gradientMap.getContext( '2d' );
84 _gradientMapContext.translate( - _gradientMapQuality / 2, - _gradientMapQuality / 2 );
85 _gradientMapContext.scale( _gradientMapQuality, _gradientMapQuality );
86
87 _gradientMapQuality --; // Fix UVs
88
89 this.domElement = _canvas;
90
91 this.autoClear = true;
92 this.sortObjects = true;
93 this.sortElements = true;
94
95 this.info = {
96
97 render: {
98
99 vertices: 0,
100 faces: 0
101
102 }
103
104 }
105
106 this.setSize = function ( width, height ) {
107
108 _canvasWidth = width;
109 _canvasHeight = height;
110 _canvasWidthHalf = Math.floor( _canvasWidth / 2 );
111 _canvasHeightHalf = Math.floor( _canvasHeight / 2 );
112
113 _canvas.width = _canvasWidth;
114 _canvas.height = _canvasHeight;
115
116 _clipRect.set( - _canvasWidthHalf, - _canvasHeightHalf, _canvasWidthHalf, _canvasHeightHalf );
117 _clearRect.set( - _canvasWidthHalf, - _canvasHeightHalf, _canvasWidthHalf, _canvasHeightHalf );
118
119 _contextGlobalAlpha = 1;
120 _contextGlobalCompositeOperation = 0;
121 _contextStrokeStyle = null;
122 _contextFillStyle = null;
123 _contextLineWidth = null;
124 _contextLineCap = null;
125 _contextLineJoin = null;
126
127 };
128
129 this.setClearColor = function ( color, opacity ) {
130
131 _clearColor.copy( color );
132 _clearOpacity = opacity !== undefined ? opacity : 1;
133
134 _clearRect.set( - _canvasWidthHalf, - _canvasHeightHalf, _canvasWidthHalf, _canvasHeightHalf );
135
136 };
137
138 this.setClearColorHex = function ( hex, opacity ) {
139
140 _clearColor.setHex( hex );
141 _clearOpacity = opacity !== undefined ? opacity : 1;
142
143 _clearRect.set( - _canvasWidthHalf, - _canvasHeightHalf, _canvasWidthHalf, _canvasHeightHalf );
144
145 };
146
147 this.getMaxAnisotropy = function () {
148
149 return 0;
150
151 };
152
153 this.clear = function () {
154
155 _context.setTransform( 1, 0, 0, - 1, _canvasWidthHalf, _canvasHeightHalf );
156
157 if ( _clearRect.isEmpty() === false ) {
158
159 _clearRect.minSelf( _clipRect );
160 _clearRect.inflate( 2 );
161
162 if ( _clearOpacity < 1 ) {
163
164 _context.clearRect( Math.floor( _clearRect.getX() ), Math.floor( _clearRect.getY() ), Math.floor( _clearRect.getWidth() ), Math.floor( _clearRect.getHeight() ) );
165
166 }
167
168 if ( _clearOpacity > 0 ) {
169
170 setBlending( THREE.NormalBlending );
171 setOpacity( 1 );
172
173 setFillStyle( 'rgba(' + Math.floor( _clearColor.r * 255 ) + ',' + Math.floor( _clearColor.g * 255 ) + ',' + Math.floor( _clearColor.b * 255 ) + ',' + _clearOpacity + ')' );
174
175 _context.fillRect( Math.floor( _clearRect.getX() ), Math.floor( _clearRect.getY() ), Math.floor( _clearRect.getWidth() ), Math.floor( _clearRect.getHeight() ) );
176
177 }
178
179 _clearRect.empty();
180
181 }
182
183
184 };
185
186 this.render = function ( scene, camera ) {
187
188 if ( camera instanceof THREE.Camera === false ) {
189
190 console.error( 'THREE.CanvasRenderer.render: camera is not an instance of THREE.Camera.' );
191 return;
192
193 }
194
195 var e, el, element, material;
196
197 this.autoClear === true
198 ? this.clear()
199 : _context.setTransform( 1, 0, 0, - 1, _canvasWidthHalf, _canvasHeightHalf );
200
201 _this.info.render.vertices = 0;
202 _this.info.render.faces = 0;
203
204 _renderData = _projector.projectScene( scene, camera, this.sortObjects, this.sortElements );
205 _elements = _renderData.elements;
206 _lights = _renderData.lights;
207
208 /* DEBUG
209 _context.fillStyle = 'rgba( 0, 255, 255, 0.5 )';
210 _context.fillRect( _clipRect.getX(), _clipRect.getY(), _clipRect.getWidth(), _clipRect.getHeight() );
211 */
212
213 _enableLighting = _lights.length > 0;
214
215 if ( _enableLighting === true ) {
216
217 calculateLights();
218
219 }
220
221 for ( e = 0, el = _elements.length; e < el; e++ ) {
222
223 element = _elements[ e ];
224
225 material = element.material;
226
227 if ( material === undefined || material.visible === false ) continue;
228
229 _bboxRect.empty();
230
231 if ( element instanceof THREE.RenderableParticle ) {
232
233 _v1 = element;
234 _v1.x *= _canvasWidthHalf; _v1.y *= _canvasHeightHalf;
235
236 renderParticle( _v1, element, material, scene );
237
238 } else if ( element instanceof THREE.RenderableLine ) {
239
240 _v1 = element.v1; _v2 = element.v2;
241
242 _v1.positionScreen.x *= _canvasWidthHalf; _v1.positionScreen.y *= _canvasHeightHalf;
243 _v2.positionScreen.x *= _canvasWidthHalf; _v2.positionScreen.y *= _canvasHeightHalf;
244
245 _bboxRect.addPoint( _v1.positionScreen.x, _v1.positionScreen.y );
246 _bboxRect.addPoint( _v2.positionScreen.x, _v2.positionScreen.y );
247
248 if ( _clipRect.intersects( _bboxRect ) === true ) {
249
250 renderLine( _v1, _v2, element, material, scene );
251
252 }
253
254
255 } else if ( element instanceof THREE.RenderableFace3 ) {
256
257 _v1 = element.v1; _v2 = element.v2; _v3 = element.v3;
258
259 _v1.positionScreen.x *= _canvasWidthHalf; _v1.positionScreen.y *= _canvasHeightHalf;
260 _v2.positionScreen.x *= _canvasWidthHalf; _v2.positionScreen.y *= _canvasHeightHalf;
261 _v3.positionScreen.x *= _canvasWidthHalf; _v3.positionScreen.y *= _canvasHeightHalf;
262
263 if ( material.overdraw === true ) {
264
265 expand( _v1.positionScreen, _v2.positionScreen );
266 expand( _v2.positionScreen, _v3.positionScreen );
267 expand( _v3.positionScreen, _v1.positionScreen );
268
269 }
270
271 _bboxRect.add3Points( _v1.positionScreen.x, _v1.positionScreen.y,
272 _v2.positionScreen.x, _v2.positionScreen.y,
273 _v3.positionScreen.x, _v3.positionScreen.y );
274
275 if ( _clipRect.intersects( _bboxRect ) === true ) {
276
277 renderFace3( _v1, _v2, _v3, 0, 1, 2, element, material, scene );
278
279 }
280
281 } else if ( element instanceof THREE.RenderableFace4 ) {
282
283 _v1 = element.v1; _v2 = element.v2; _v3 = element.v3; _v4 = element.v4;
284
285 _v1.positionScreen.x *= _canvasWidthHalf; _v1.positionScreen.y *= _canvasHeightHalf;
286 _v2.positionScreen.x *= _canvasWidthHalf; _v2.positionScreen.y *= _canvasHeightHalf;
287 _v3.positionScreen.x *= _canvasWidthHalf; _v3.positionScreen.y *= _canvasHeightHalf;
288 _v4.positionScreen.x *= _canvasWidthHalf; _v4.positionScreen.y *= _canvasHeightHalf;
289
290 _v5.positionScreen.copy( _v2.positionScreen );
291 _v6.positionScreen.copy( _v4.positionScreen );
292
293 if ( material.overdraw === true ) {
294
295 expand( _v1.positionScreen, _v2.positionScreen );
296 expand( _v2.positionScreen, _v4.positionScreen );
297 expand( _v4.positionScreen, _v1.positionScreen );
298
299 expand( _v3.positionScreen, _v5.positionScreen );
300 expand( _v3.positionScreen, _v6.positionScreen );
301
302 }
303
304 _bboxRect.addPoint( _v1.positionScreen.x, _v1.positionScreen.y );
305 _bboxRect.addPoint( _v2.positionScreen.x, _v2.positionScreen.y );
306 _bboxRect.addPoint( _v3.positionScreen.x, _v3.positionScreen.y );
307 _bboxRect.addPoint( _v4.positionScreen.x, _v4.positionScreen.y );
308
309 if ( _clipRect.intersects( _bboxRect ) === true ) {
310
311 renderFace4( _v1, _v2, _v3, _v4, _v5, _v6, element, material, scene );
312
313 }
314
315 }
316
317 /* DEBUG
318 _context.lineWidth = 1;
319 _context.strokeStyle = 'rgba( 0, 255, 0, 0.5 )';
320 _context.strokeRect( _bboxRect.getX(), _bboxRect.getY(), _bboxRect.getWidth(), _bboxRect.getHeight() );
321 */
322
323 _clearRect.addRectangle( _bboxRect );
324
325
326 }
327
328 /* DEBUG
329 _context.lineWidth = 1;
330 _context.strokeStyle = 'rgba( 255, 0, 0, 0.5 )';
331 _context.strokeRect( _clearRect.getX(), _clearRect.getY(), _clearRect.getWidth(), _clearRect.getHeight() );
332 */
333
334 _context.setTransform( 1, 0, 0, 1, 0, 0 );
335
336 //
337
338 function calculateLights() {
339
340 _ambientLight.setRGB( 0, 0, 0 );
341 _directionalLights.setRGB( 0, 0, 0 );
342 _pointLights.setRGB( 0, 0, 0 );
343
344 for ( var l = 0, ll = _lights.length; l < ll; l ++ ) {
345
346 var light = _lights[ l ];
347 var lightColor = light.color;
348
349 if ( light instanceof THREE.AmbientLight ) {
350
351 _ambientLight.r += lightColor.r;
352 _ambientLight.g += lightColor.g;
353 _ambientLight.b += lightColor.b;
354
355 } else if ( light instanceof THREE.DirectionalLight ) {
356
357 // for particles
358
359 _directionalLights.r += lightColor.r;
360 _directionalLights.g += lightColor.g;
361 _directionalLights.b += lightColor.b;
362
363 } else if ( light instanceof THREE.PointLight ) {
364
365 // for particles
366
367 _pointLights.r += lightColor.r;
368 _pointLights.g += lightColor.g;
369 _pointLights.b += lightColor.b;
370
371 }
372
373 }
374
375 }
376
377 function calculateLight( position, normal, color ) {
378
379 for ( var l = 0, ll = _lights.length; l < ll; l ++ ) {
380
381 var light = _lights[ l ];
382 var lightColor = light.color;
383
384 if ( light instanceof THREE.DirectionalLight ) {
385
386 var lightPosition = light.matrixWorld.getPosition().normalize();
387
388 var amount = normal.dot( lightPosition );
389
390 if ( amount <= 0 ) continue;
391
392 amount *= light.intensity;
393
394 color.r += lightColor.r * amount;
395 color.g += lightColor.g * amount;
396 color.b += lightColor.b * amount;
397
398 } else if ( light instanceof THREE.PointLight ) {
399
400 var lightPosition = light.matrixWorld.getPosition();
401
402 var amount = normal.dot( _vector3.sub( lightPosition, position ).normalize() );
403
404 if ( amount <= 0 ) continue;
405
406 amount *= light.distance == 0 ? 1 : 1 - Math.min( position.distanceTo( lightPosition ) / light.distance, 1 );
407
408 if ( amount == 0 ) continue;
409
410 amount *= light.intensity;
411
412 color.r += lightColor.r * amount;
413 color.g += lightColor.g * amount;
414 color.b += lightColor.b * amount;
415
416 }
417
418 }
419
420 }
421
422 function renderParticle( v1, element, material, scene ) {
423
424 setOpacity( material.opacity );
425 setBlending( material.blending );
426
427 var width, height, scaleX, scaleY,
428 bitmap, bitmapWidth, bitmapHeight;
429
430 if ( material instanceof THREE.ParticleBasicMaterial ) {
431
432 if ( material.map === null ) {
433
434 scaleX = element.object.scale.x;
435 scaleY = element.object.scale.y;
436
437 // TODO: Be able to disable this
438
439 scaleX *= element.scale.x * _canvasWidthHalf;
440 scaleY *= element.scale.y * _canvasHeightHalf;
441
442 _bboxRect.set( v1.x - scaleX, v1.y - scaleY, v1.x + scaleX, v1.y + scaleY );
443
444 if ( _clipRect.intersects( _bboxRect ) === false ) {
445
446 return;
447
448 }
449
450 setFillStyle( material.color.getContextStyle() );
451
452 _context.save();
453 _context.translate( v1.x, v1.y );
454 _context.rotate( - element.rotation );
455 _context.scale( scaleX, scaleY );
456 _context.fillRect( -1, -1, 2, 2 );
457 _context.restore();
458
459 } else {
460
461 bitmap = material.map.image;
462 bitmapWidth = bitmap.width >> 1;
463 bitmapHeight = bitmap.height >> 1;
464
465 scaleX = element.scale.x * _canvasWidthHalf;
466 scaleY = element.scale.y * _canvasHeightHalf;
467
468 width = scaleX * bitmapWidth;
469 height = scaleY * bitmapHeight;
470
471 // TODO: Rotations break this...
472
473 _bboxRect.set( v1.x - width, v1.y - height, v1.x + width, v1.y + height );
474
475 if ( _clipRect.intersects( _bboxRect ) === false ) {
476
477 return;
478
479 }
480
481 _context.save();
482 _context.translate( v1.x, v1.y );
483 _context.rotate( - element.rotation );
484 _context.scale( scaleX, - scaleY );
485
486 _context.translate( - bitmapWidth, - bitmapHeight );
487 _context.drawImage( bitmap, 0, 0 );
488 _context.restore();
489
490 }
491
492 /* DEBUG
493 setStrokeStyle( 'rgb(255,255,0)' );
494 _context.beginPath();
495 _context.moveTo( v1.x - 10, v1.y );
496 _context.lineTo( v1.x + 10, v1.y );
497 _context.moveTo( v1.x, v1.y - 10 );
498 _context.lineTo( v1.x, v1.y + 10 );
499 _context.stroke();
500 */
501
502 } else if ( material instanceof THREE.ParticleCanvasMaterial ) {
503
504 width = element.scale.x * _canvasWidthHalf;
505 height = element.scale.y * _canvasHeightHalf;
506
507 _bboxRect.set( v1.x - width, v1.y - height, v1.x + width, v1.y + height );
508
509 if ( _clipRect.intersects( _bboxRect ) === false ) {
510
511 return;
512
513 }
514
515 setStrokeStyle( material.color.getContextStyle() );
516 setFillStyle( material.color.getContextStyle() );
517
518 _context.save();
519 _context.translate( v1.x, v1.y );
520 _context.rotate( - element.rotation );
521 _context.scale( width, height );
522
523 material.program( _context );
524
525 _context.restore();
526
527 }
528
529 }
530
531 function renderLine( v1, v2, element, material, scene ) {
532
533 setOpacity( material.opacity );
534 setBlending( material.blending );
535
536 _context.beginPath();
537 _context.moveTo( v1.positionScreen.x, v1.positionScreen.y );
538 _context.lineTo( v2.positionScreen.x, v2.positionScreen.y );
539
540 if ( material instanceof THREE.LineBasicMaterial ) {
541
542 setLineWidth( material.linewidth );
543 setLineCap( material.linecap );
544 setLineJoin( material.linejoin );
545 setStrokeStyle( material.color.getContextStyle() );
546
547 _context.stroke();
548 _bboxRect.inflate( material.linewidth * 2 );
549
550 }
551
552 }
553
554 function renderFace3( v1, v2, v3, uv1, uv2, uv3, element, material, scene ) {
555
556 _this.info.render.vertices += 3;
557 _this.info.render.faces ++;
558
559 setOpacity( material.opacity );
560 setBlending( material.blending );
561
562 _v1x = v1.positionScreen.x; _v1y = v1.positionScreen.y;
563 _v2x = v2.positionScreen.x; _v2y = v2.positionScreen.y;
564 _v3x = v3.positionScreen.x; _v3y = v3.positionScreen.y;
565
566 drawTriangle( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y );
567
568 if ( ( material instanceof THREE.MeshLambertMaterial || material instanceof THREE.MeshPhongMaterial ) && material.map === null && material.map === null ) {
569
570 _diffuseColor.copy( material.color );
571 _emissiveColor.copy( material.emissive );
572
573 if ( material.vertexColors === THREE.FaceColors ) {
574
575 _diffuseColor.r *= element.color.r;
576 _diffuseColor.g *= element.color.g;
577 _diffuseColor.b *= element.color.b;
578
579 }
580
581 if ( _enableLighting === true ) {
582
583 if ( material.wireframe === false && material.shading == THREE.SmoothShading && element.vertexNormalsLength == 3 ) {
584
585 _color1.r = _color2.r = _color3.r = _ambientLight.r;
586 _color1.g = _color2.g = _color3.g = _ambientLight.g;
587 _color1.b = _color2.b = _color3.b = _ambientLight.b;
588
589 calculateLight( element.v1.positionWorld, element.vertexNormalsWorld[ 0 ], _color1 );
590 calculateLight( element.v2.positionWorld, element.vertexNormalsWorld[ 1 ], _color2 );
591 calculateLight( element.v3.positionWorld, element.vertexNormalsWorld[ 2 ], _color3 );
592
593 _color1.r = _color1.r * _diffuseColor.r + _emissiveColor.r;
594 _color1.g = _color1.g * _diffuseColor.g + _emissiveColor.g;
595 _color1.b = _color1.b * _diffuseColor.b + _emissiveColor.b;
596
597 _color2.r = _color2.r * _diffuseColor.r + _emissiveColor.r;
598 _color2.g = _color2.g * _diffuseColor.g + _emissiveColor.g;
599 _color2.b = _color2.b * _diffuseColor.b + _emissiveColor.b;
600
601 _color3.r = _color3.r * _diffuseColor.r + _emissiveColor.r;
602 _color3.g = _color3.g * _diffuseColor.g + _emissiveColor.g;
603 _color3.b = _color3.b * _diffuseColor.b + _emissiveColor.b;
604
605 _color4.r = ( _color2.r + _color3.r ) * 0.5;
606 _color4.g = ( _color2.g + _color3.g ) * 0.5;
607 _color4.b = ( _color2.b + _color3.b ) * 0.5;
608
609 _image = getGradientTexture( _color1, _color2, _color3, _color4 );
610
611 clipImage( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, 0, 0, 1, 0, 0, 1, _image );
612
613 } else {
614
615 _color.r = _ambientLight.r;
616 _color.g = _ambientLight.g;
617 _color.b = _ambientLight.b;
618
619 calculateLight( element.centroidWorld, element.normalWorld, _color );
620
621 _color.r = _color.r * _diffuseColor.r + _emissiveColor.r;
622 _color.g = _color.g * _diffuseColor.g + _emissiveColor.g;
623 _color.b = _color.b * _diffuseColor.b + _emissiveColor.b;
624
625 material.wireframe === true
626 ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin )
627 : fillPath( _color );
628
629 }
630
631 } else {
632
633 material.wireframe === true
634 ? strokePath( material.color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin )
635 : fillPath( material.color );
636
637 }
638
639 } else if ( material instanceof THREE.MeshBasicMaterial || material instanceof THREE.MeshLambertMaterial || material instanceof THREE.MeshPhongMaterial ) {
640
641 if ( material.map !== null ) {
642
643 if ( material.map.mapping instanceof THREE.UVMapping ) {
644
645 _uvs = element.uvs[ 0 ];
646 patternPath( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _uvs[ uv1 ].u, _uvs[ uv1 ].v, _uvs[ uv2 ].u, _uvs[ uv2 ].v, _uvs[ uv3 ].u, _uvs[ uv3 ].v, material.map );
647
648 }
649
650
651 } else if ( material.envMap !== null ) {
652
653 if ( material.envMap.mapping instanceof THREE.SphericalReflectionMapping ) {
654
655 var cameraMatrix = camera.matrixWorldInverse;
656
657 _vector3.copy( element.vertexNormalsWorld[ uv1 ] );
658 _uv1x = ( _vector3.x * cameraMatrix.elements[0] + _vector3.y * cameraMatrix.elements[4] + _vector3.z * cameraMatrix.elements[8] ) * 0.5 + 0.5;
659 _uv1y = ( _vector3.x * cameraMatrix.elements[1] + _vector3.y * cameraMatrix.elements[5] + _vector3.z * cameraMatrix.elements[9] ) * 0.5 + 0.5;
660
661 _vector3.copy( element.vertexNormalsWorld[ uv2 ] );
662 _uv2x = ( _vector3.x * cameraMatrix.elements[0] + _vector3.y * cameraMatrix.elements[4] + _vector3.z * cameraMatrix.elements[8] ) * 0.5 + 0.5;
663 _uv2y = ( _vector3.x * cameraMatrix.elements[1] + _vector3.y * cameraMatrix.elements[5] + _vector3.z * cameraMatrix.elements[9] ) * 0.5 + 0.5;
664
665 _vector3.copy( element.vertexNormalsWorld[ uv3 ] );
666 _uv3x = ( _vector3.x * cameraMatrix.elements[0] + _vector3.y * cameraMatrix.elements[4] + _vector3.z * cameraMatrix.elements[8] ) * 0.5 + 0.5;
667 _uv3y = ( _vector3.x * cameraMatrix.elements[1] + _vector3.y * cameraMatrix.elements[5] + _vector3.z * cameraMatrix.elements[9] ) * 0.5 + 0.5;
668
669 patternPath( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _uv1x, _uv1y, _uv2x, _uv2y, _uv3x, _uv3y, material.envMap );
670
671 }/* else if ( material.envMap.mapping == THREE.SphericalRefractionMapping ) {
672
673
674
675 }*/
676
677
678 } else {
679
680 _color.copy( material.color );
681
682 if ( material.vertexColors === THREE.FaceColors ) {
683
684 _color.r *= element.color.r;
685 _color.g *= element.color.g;
686 _color.b *= element.color.b;
687
688 }
689
690 material.wireframe === true
691 ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin )
692 : fillPath( _color );
693
694 }
695
696 } else if ( material instanceof THREE.MeshDepthMaterial ) {
697
698 _near = camera.near;
699 _far = camera.far;
700
701 _color1.r = _color1.g = _color1.b = 1 - smoothstep( v1.positionScreen.z, _near, _far );
702 _color2.r = _color2.g = _color2.b = 1 - smoothstep( v2.positionScreen.z, _near, _far );
703 _color3.r = _color3.g = _color3.b = 1 - smoothstep( v3.positionScreen.z, _near, _far );
704
705 _color4.r = ( _color2.r + _color3.r ) * 0.5;
706 _color4.g = ( _color2.g + _color3.g ) * 0.5;
707 _color4.b = ( _color2.b + _color3.b ) * 0.5;
708
709 _image = getGradientTexture( _color1, _color2, _color3, _color4 );
710
711 clipImage( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, 0, 0, 1, 0, 0, 1, _image );
712
713 } else if ( material instanceof THREE.MeshNormalMaterial ) {
714
715 _color.r = normalToComponent( element.normalWorld.x );
716 _color.g = normalToComponent( element.normalWorld.y );
717 _color.b = normalToComponent( element.normalWorld.z );
718
719 material.wireframe === true
720 ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin )
721 : fillPath( _color );
722
723 }
724
725 }
726
727 function renderFace4( v1, v2, v3, v4, v5, v6, element, material, scene ) {
728
729 _this.info.render.vertices += 4;
730 _this.info.render.faces ++;
731
732 setOpacity( material.opacity );
733 setBlending( material.blending );
734
735 if ( ( material.map !== undefined && material.map !== null ) || ( material.envMap !== undefined && material.envMap !== null ) ) {
736
737 // Let renderFace3() handle this
738
739 renderFace3( v1, v2, v4, 0, 1, 3, element, material, scene );
740 renderFace3( v5, v3, v6, 1, 2, 3, element, material, scene );
741
742 return;
743
744 }
745
746 _v1x = v1.positionScreen.x; _v1y = v1.positionScreen.y;
747 _v2x = v2.positionScreen.x; _v2y = v2.positionScreen.y;
748 _v3x = v3.positionScreen.x; _v3y = v3.positionScreen.y;
749 _v4x = v4.positionScreen.x; _v4y = v4.positionScreen.y;
750 _v5x = v5.positionScreen.x; _v5y = v5.positionScreen.y;
751 _v6x = v6.positionScreen.x; _v6y = v6.positionScreen.y;
752
753 if ( material instanceof THREE.MeshLambertMaterial || material instanceof THREE.MeshPhongMaterial ) {
754
755 _diffuseColor.copy( material.color );
756 _emissiveColor.copy( material.emissive );
757
758 if ( material.vertexColors === THREE.FaceColors ) {
759
760 _diffuseColor.r *= element.color.r;
761 _diffuseColor.g *= element.color.g;
762 _diffuseColor.b *= element.color.b;
763
764 }
765
766 if ( _enableLighting === true ) {
767
768 if ( material.wireframe === false && material.shading == THREE.SmoothShading && element.vertexNormalsLength == 4 ) {
769
770 _color1.r = _color2.r = _color3.r = _color4.r = _ambientLight.r;
771 _color1.g = _color2.g = _color3.g = _color4.g = _ambientLight.g;
772 _color1.b = _color2.b = _color3.b = _color4.b = _ambientLight.b;
773
774 calculateLight( element.v1.positionWorld, element.vertexNormalsWorld[ 0 ], _color1 );
775 calculateLight( element.v2.positionWorld, element.vertexNormalsWorld[ 1 ], _color2 );
776 calculateLight( element.v4.positionWorld, element.vertexNormalsWorld[ 3 ], _color3 );
777 calculateLight( element.v3.positionWorld, element.vertexNormalsWorld[ 2 ], _color4 );
778
779 _color1.r = _color1.r * _diffuseColor.r + _emissiveColor.r;
780 _color1.g = _color1.g * _diffuseColor.g + _emissiveColor.g;
781 _color1.b = _color1.b * _diffuseColor.b + _emissiveColor.b;
782
783 _color2.r = _color2.r * _diffuseColor.r + _emissiveColor.r;
784 _color2.g = _color2.g * _diffuseColor.g + _emissiveColor.g;
785 _color2.b = _color2.b * _diffuseColor.b + _emissiveColor.b;
786
787 _color3.r = _color3.r * _diffuseColor.r + _emissiveColor.r;
788 _color3.g = _color3.g * _diffuseColor.g + _emissiveColor.g;
789 _color3.b = _color3.b * _diffuseColor.b + _emissiveColor.b;
790
791 _color4.r = _color4.r * _diffuseColor.r + _emissiveColor.r;
792 _color4.g = _color4.g * _diffuseColor.g + _emissiveColor.g;
793 _color4.b = _color4.b * _diffuseColor.b + _emissiveColor.b;
794
795 _image = getGradientTexture( _color1, _color2, _color3, _color4 );
796
797 // TODO: UVs are incorrect, v4->v3?
798
799 drawTriangle( _v1x, _v1y, _v2x, _v2y, _v4x, _v4y );
800 clipImage( _v1x, _v1y, _v2x, _v2y, _v4x, _v4y, 0, 0, 1, 0, 0, 1, _image );
801
802 drawTriangle( _v5x, _v5y, _v3x, _v3y, _v6x, _v6y );
803 clipImage( _v5x, _v5y, _v3x, _v3y, _v6x, _v6y, 1, 0, 1, 1, 0, 1, _image );
804
805 } else {
806
807 _color.r = _ambientLight.r;
808 _color.g = _ambientLight.g;
809 _color.b = _ambientLight.b;
810
811 calculateLight( element.centroidWorld, element.normalWorld, _color );
812
813 _color.r = _color.r * _diffuseColor.r + _emissiveColor.r;
814 _color.g = _color.g * _diffuseColor.g + _emissiveColor.g;
815 _color.b = _color.b * _diffuseColor.b + _emissiveColor.b;
816
817 drawQuad( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _v4x, _v4y );
818
819 material.wireframe === true
820 ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin )
821 : fillPath( _color );
822
823 }
824
825 } else {
826
827 _color.r = _diffuseColor.r + _emissiveColor.r;
828 _color.g = _diffuseColor.g + _emissiveColor.g;
829 _color.b = _diffuseColor.b + _emissiveColor.b;
830
831 drawQuad( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _v4x, _v4y );
832
833 material.wireframe === true
834 ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin )
835 : fillPath( _color );
836
837 }
838
839 } else if ( material instanceof THREE.MeshBasicMaterial ) {
840
841 _color.copy( material.color );
842
843 if ( material.vertexColors === THREE.FaceColors ) {
844
845 _color.r *= element.color.r;
846 _color.g *= element.color.g;
847 _color.b *= element.color.b;
848
849 }
850
851 drawQuad( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _v4x, _v4y );
852
853 material.wireframe === true
854 ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin )
855 : fillPath( _color );
856
857 } else if ( material instanceof THREE.MeshNormalMaterial ) {
858
859 _color.r = normalToComponent( element.normalWorld.x );
860 _color.g = normalToComponent( element.normalWorld.y );
861 _color.b = normalToComponent( element.normalWorld.z );
862
863 drawQuad( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _v4x, _v4y );
864
865 material.wireframe === true
866 ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin )
867 : fillPath( _color );
868
869 } else if ( material instanceof THREE.MeshDepthMaterial ) {
870
871 _near = camera.near;
872 _far = camera.far;
873
874 _color1.r = _color1.g = _color1.b = 1 - smoothstep( v1.positionScreen.z, _near, _far );
875 _color2.r = _color2.g = _color2.b = 1 - smoothstep( v2.positionScreen.z, _near, _far );
876 _color3.r = _color3.g = _color3.b = 1 - smoothstep( v4.positionScreen.z, _near, _far );
877 _color4.r = _color4.g = _color4.b = 1 - smoothstep( v3.positionScreen.z, _near, _far );
878
879 _image = getGradientTexture( _color1, _color2, _color3, _color4 );
880
881 // TODO: UVs are incorrect, v4->v3?
882
883 drawTriangle( _v1x, _v1y, _v2x, _v2y, _v4x, _v4y );
884 clipImage( _v1x, _v1y, _v2x, _v2y, _v4x, _v4y, 0, 0, 1, 0, 0, 1, _image );
885
886 drawTriangle( _v5x, _v5y, _v3x, _v3y, _v6x, _v6y );
887 clipImage( _v5x, _v5y, _v3x, _v3y, _v6x, _v6y, 1, 0, 1, 1, 0, 1, _image );
888
889 }
890
891 }
892
893 //
894
895 function drawTriangle( x0, y0, x1, y1, x2, y2 ) {
896
897 _context.beginPath();
898 _context.moveTo( x0, y0 );
899 _context.lineTo( x1, y1 );
900 _context.lineTo( x2, y2 );
901 _context.closePath();
902
903 }
904
905 function drawQuad( x0, y0, x1, y1, x2, y2, x3, y3 ) {
906
907 _context.beginPath();
908 _context.moveTo( x0, y0 );
909 _context.lineTo( x1, y1 );
910 _context.lineTo( x2, y2 );
911 _context.lineTo( x3, y3 );
912 _context.closePath();
913
914 }
915
916 function strokePath( color, linewidth, linecap, linejoin ) {
917
918 setLineWidth( linewidth );
919 setLineCap( linecap );
920 setLineJoin( linejoin );
921 setStrokeStyle( color.getContextStyle() );
922
923 _context.stroke();
924
925 _bboxRect.inflate( linewidth * 2 );
926
927 }
928
929 function fillPath( color ) {
930
931 setFillStyle( color.getContextStyle() );
932 _context.fill();
933
934 }
935
936 function patternPath( x0, y0, x1, y1, x2, y2, u0, v0, u1, v1, u2, v2, texture ) {
937
938 if ( texture instanceof THREE.DataTexture || texture.image === undefined || texture.image.width == 0 ) return;
939
940 if ( texture.needsUpdate === true ) {
941
942 var repeatX = texture.wrapS == THREE.RepeatWrapping;
943 var repeatY = texture.wrapT == THREE.RepeatWrapping;
944
945 _patterns[ texture.id ] = _context.createPattern(
946 texture.image, repeatX === true && repeatY === true
947 ? 'repeat'
948 : repeatX === true && repeatY === false
949 ? 'repeat-x'
950 : repeatX === false && repeatY === true
951 ? 'repeat-y'
952 : 'no-repeat'
953 );
954
955 texture.needsUpdate = false;
956
957 }
958
959 _patterns[ texture.id ] === undefined
960 ? setFillStyle( 'rgba(0,0,0,1)' )
961 : setFillStyle( _patterns[ texture.id ] );
962
963 // http://extremelysatisfactorytotalitarianism.com/blog/?p=2120
964
965 var a, b, c, d, e, f, det, idet,
966 offsetX = texture.offset.x / texture.repeat.x,
967 offsetY = texture.offset.y / texture.repeat.y,
968 width = texture.image.width * texture.repeat.x,
969 height = texture.image.height * texture.repeat.y;
970
971 u0 = ( u0 + offsetX ) * width;
972 v0 = ( 1.0 - v0 + offsetY ) * height;
973
974 u1 = ( u1 + offsetX ) * width;
975 v1 = ( 1.0 - v1 + offsetY ) * height;
976
977 u2 = ( u2 + offsetX ) * width;
978 v2 = ( 1.0 - v2 + offsetY ) * height;
979
980 x1 -= x0; y1 -= y0;
981 x2 -= x0; y2 -= y0;
982
983 u1 -= u0; v1 -= v0;
984 u2 -= u0; v2 -= v0;
985
986 det = u1 * v2 - u2 * v1;
987
988 if ( det === 0 ) {
989
990 if ( _imagedatas[ texture.id ] === undefined ) {
991
992 var canvas = document.createElement( 'canvas' )
993 canvas.width = texture.image.width;
994 canvas.height = texture.image.height;
995
996 var context = canvas.getContext( '2d' );
997 context.drawImage( texture.image, 0, 0 );
998
999 _imagedatas[ texture.id ] = context.getImageData( 0, 0, texture.image.width, texture.image.height ).data;
1000
1001 }
1002
1003 var data = _imagedatas[ texture.id ];
1004 var index = ( Math.floor( u0 ) + Math.floor( v0 ) * texture.image.width ) * 4;
1005
1006 _color.setRGB( data[ index ] / 255, data[ index + 1 ] / 255, data[ index + 2 ] / 255 );
1007 fillPath( _color );
1008
1009 return;
1010
1011 }
1012
1013 idet = 1 / det;
1014
1015 a = ( v2 * x1 - v1 * x2 ) * idet;
1016 b = ( v2 * y1 - v1 * y2 ) * idet;
1017 c = ( u1 * x2 - u2 * x1 ) * idet;
1018 d = ( u1 * y2 - u2 * y1 ) * idet;
1019
1020 e = x0 - a * u0 - c * v0;
1021 f = y0 - b * u0 - d * v0;
1022
1023 _context.save();
1024 _context.transform( a, b, c, d, e, f );
1025 _context.fill();
1026 _context.restore();
1027
1028 }
1029
1030 function clipImage( x0, y0, x1, y1, x2, y2, u0, v0, u1, v1, u2, v2, image ) {
1031
1032 // http://extremelysatisfactorytotalitarianism.com/blog/?p=2120
1033
1034 var a, b, c, d, e, f, det, idet,
1035 width = image.width - 1,
1036 height = image.height - 1;
1037
1038 u0 *= width; v0 *= height;
1039 u1 *= width; v1 *= height;
1040 u2 *= width; v2 *= height;
1041
1042 x1 -= x0; y1 -= y0;
1043 x2 -= x0; y2 -= y0;
1044
1045 u1 -= u0; v1 -= v0;
1046 u2 -= u0; v2 -= v0;
1047
1048 det = u1 * v2 - u2 * v1;
1049
1050 idet = 1 / det;
1051
1052 a = ( v2 * x1 - v1 * x2 ) * idet;
1053 b = ( v2 * y1 - v1 * y2 ) * idet;
1054 c = ( u1 * x2 - u2 * x1 ) * idet;
1055 d = ( u1 * y2 - u2 * y1 ) * idet;
1056
1057 e = x0 - a * u0 - c * v0;
1058 f = y0 - b * u0 - d * v0;
1059
1060 _context.save();
1061 _context.transform( a, b, c, d, e, f );
1062 _context.clip();
1063 _context.drawImage( image, 0, 0 );
1064 _context.restore();
1065
1066 }
1067
1068 function getGradientTexture( color1, color2, color3, color4 ) {
1069
1070 // http://mrdoob.com/blog/post/710
1071
1072 _pixelMapData[ 0 ] = ( color1.r * 255 ) | 0;
1073 _pixelMapData[ 1 ] = ( color1.g * 255 ) | 0;
1074 _pixelMapData[ 2 ] = ( color1.b * 255 ) | 0;
1075
1076 _pixelMapData[ 4 ] = ( color2.r * 255 ) | 0;
1077 _pixelMapData[ 5 ] = ( color2.g * 255 ) | 0;
1078 _pixelMapData[ 6 ] = ( color2.b * 255 ) | 0;
1079
1080 _pixelMapData[ 8 ] = ( color3.r * 255 ) | 0;
1081 _pixelMapData[ 9 ] = ( color3.g * 255 ) | 0;
1082 _pixelMapData[ 10 ] = ( color3.b * 255 ) | 0;
1083
1084 _pixelMapData[ 12 ] = ( color4.r * 255 ) | 0;
1085 _pixelMapData[ 13 ] = ( color4.g * 255 ) | 0;
1086 _pixelMapData[ 14 ] = ( color4.b * 255 ) | 0;
1087
1088 _pixelMapContext.putImageData( _pixelMapImage, 0, 0 );
1089 _gradientMapContext.drawImage( _pixelMap, 0, 0 );
1090
1091 return _gradientMap;
1092
1093 }
1094
1095 function smoothstep( value, min, max ) {
1096
1097 var x = ( value - min ) / ( max - min );
1098 return x * x * ( 3 - 2 * x );
1099
1100 }
1101
1102 function normalToComponent( normal ) {
1103
1104 var component = ( normal + 1 ) * 0.5;
1105 return component < 0 ? 0 : ( component > 1 ? 1 : component );
1106
1107 }
1108
1109 // Hide anti-alias gaps
1110
1111 function expand( v1, v2 ) {
1112
1113 var x = v2.x - v1.x, y = v2.y - v1.y,
1114 det = x * x + y * y, idet;
1115
1116 if ( det === 0 ) return;
1117
1118 idet = 1 / Math.sqrt( det );
1119
1120 x *= idet; y *= idet;
1121
1122 v2.x += x; v2.y += y;
1123 v1.x -= x; v1.y -= y;
1124
1125 }
1126 };
1127
1128 // Context cached methods.
1129
1130 function setOpacity( value ) {
1131
1132 if ( _contextGlobalAlpha !== value ) {
1133
1134 _context.globalAlpha = value;
1135 _contextGlobalAlpha = value;
1136
1137 }
1138
1139 }
1140
1141 function setBlending( value ) {
1142
1143 if ( _contextGlobalCompositeOperation !== value ) {
1144
1145 if ( value === THREE.NormalBlending ) {
1146
1147 _context.globalCompositeOperation = 'source-over';
1148
1149 } else if ( value === THREE.AdditiveBlending ) {
1150
1151 _context.globalCompositeOperation = 'lighter';
1152
1153 } else if ( value === THREE.SubtractiveBlending ) {
1154
1155 _context.globalCompositeOperation = 'darker';
1156
1157 }
1158
1159 _contextGlobalCompositeOperation = value;
1160
1161 }
1162
1163 }
1164
1165 function setLineWidth( value ) {
1166
1167 if ( _contextLineWidth !== value ) {
1168
1169 _context.lineWidth = value;
1170 _contextLineWidth = value;
1171
1172 }
1173
1174 }
1175
1176 function setLineCap( value ) {
1177
1178 // "butt", "round", "square"
1179
1180 if ( _contextLineCap !== value ) {
1181
1182 _context.lineCap = value;
1183 _contextLineCap = value;
1184
1185 }
1186
1187 }
1188
1189 function setLineJoin( value ) {
1190
1191 // "round", "bevel", "miter"
1192
1193 if ( _contextLineJoin !== value ) {
1194
1195 _context.lineJoin = value;
1196 _contextLineJoin = value;
1197
1198 }
1199
1200 }
1201
1202 function setStrokeStyle( value ) {
1203
1204 if ( _contextStrokeStyle !== value ) {
1205
1206 _context.strokeStyle = value;
1207 _contextStrokeStyle = value;
1208
1209 }
1210
1211 }
1212
1213 function setFillStyle( value ) {
1214
1215 if ( _contextFillStyle !== value ) {
1216
1217 _context.fillStyle = value;
1218 _contextFillStyle = value;
1219
1220 }
1221
1222 }
1223
1224 };
1225
nike free rn
new balance hombre baratas
cinturones gucci
ugg rebajas
cinturon gucci
ray ban baratas
nike cortez
peuterey mujer
christian louboutin madrid
mbt zapatos
gafas ray ban baratas
mbt ofertas
air max blancas
mbt barcelona
nike air max 90
woolrich barcelona
nike mujer
botas ugg
gafas de sol carrera aratas
air max 2016 baratas
oakley baratas
nike air max 2016