UNPKG

25.4 kBJavaScriptView Raw
1/**
2 * @author mrdoob / http://mrdoob.com/
3 * @author supereggbert / http://www.paulbrunt.co.uk/
4 * @author julianwa / https://github.com/julianwa
5 */
6
7THREE.RenderableObject = function () {
8
9 this.id = 0;
10
11 this.object = null;
12 this.z = 0;
13 this.renderOrder = 0;
14
15};
16
17//
18
19THREE.RenderableFace = function () {
20
21 this.id = 0;
22
23 this.v1 = new THREE.RenderableVertex();
24 this.v2 = new THREE.RenderableVertex();
25 this.v3 = new THREE.RenderableVertex();
26
27 this.normalModel = new THREE.Vector3();
28
29 this.vertexNormalsModel = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
30 this.vertexNormalsLength = 0;
31
32 this.color = new THREE.Color();
33 this.material = null;
34 this.uvs = [ new THREE.Vector2(), new THREE.Vector2(), new THREE.Vector2() ];
35
36 this.z = 0;
37 this.renderOrder = 0;
38
39};
40
41//
42
43THREE.RenderableVertex = function () {
44
45 this.position = new THREE.Vector3();
46 this.positionWorld = new THREE.Vector3();
47 this.positionScreen = new THREE.Vector4();
48
49 this.visible = true;
50
51};
52
53THREE.RenderableVertex.prototype.copy = function ( vertex ) {
54
55 this.positionWorld.copy( vertex.positionWorld );
56 this.positionScreen.copy( vertex.positionScreen );
57
58};
59
60//
61
62THREE.RenderableLine = function () {
63
64 this.id = 0;
65
66 this.v1 = new THREE.RenderableVertex();
67 this.v2 = new THREE.RenderableVertex();
68
69 this.vertexColors = [ new THREE.Color(), new THREE.Color() ];
70 this.material = null;
71
72 this.z = 0;
73 this.renderOrder = 0;
74
75};
76
77//
78
79THREE.RenderableSprite = function () {
80
81 this.id = 0;
82
83 this.object = null;
84
85 this.x = 0;
86 this.y = 0;
87 this.z = 0;
88
89 this.rotation = 0;
90 this.scale = new THREE.Vector2();
91
92 this.material = null;
93 this.renderOrder = 0;
94
95};
96
97//
98
99THREE.Projector = function () {
100
101 var _object, _objectCount, _objectPool = [], _objectPoolLength = 0,
102 _vertex, _vertexCount, _vertexPool = [], _vertexPoolLength = 0,
103 _face, _faceCount, _facePool = [], _facePoolLength = 0,
104 _line, _lineCount, _linePool = [], _linePoolLength = 0,
105 _sprite, _spriteCount, _spritePool = [], _spritePoolLength = 0,
106
107 _renderData = { objects: [], lights: [], elements: [] },
108
109 _vector3 = new THREE.Vector3(),
110 _vector4 = new THREE.Vector4(),
111
112 _clipBox = new THREE.Box3( new THREE.Vector3( - 1, - 1, - 1 ), new THREE.Vector3( 1, 1, 1 ) ),
113 _boundingBox = new THREE.Box3(),
114 _points3 = new Array( 3 ),
115
116 _viewMatrix = new THREE.Matrix4(),
117 _viewProjectionMatrix = new THREE.Matrix4(),
118
119 _modelMatrix,
120 _modelViewProjectionMatrix = new THREE.Matrix4(),
121
122 _normalMatrix = new THREE.Matrix3(),
123
124 _frustum = new THREE.Frustum(),
125
126 _clippedVertex1PositionScreen = new THREE.Vector4(),
127 _clippedVertex2PositionScreen = new THREE.Vector4();
128
129 //
130
131 this.projectVector = function ( vector, camera ) {
132
133 console.warn( 'THREE.Projector: .projectVector() is now vector.project().' );
134 vector.project( camera );
135
136 };
137
138 this.unprojectVector = function ( vector, camera ) {
139
140 console.warn( 'THREE.Projector: .unprojectVector() is now vector.unproject().' );
141 vector.unproject( camera );
142
143 };
144
145 this.pickingRay = function () {
146
147 console.error( 'THREE.Projector: .pickingRay() is now raycaster.setFromCamera().' );
148
149 };
150
151 //
152
153 var RenderList = function () {
154
155 var normals = [];
156 var colors = [];
157 var uvs = [];
158
159 var object = null;
160
161 var normalMatrix = new THREE.Matrix3();
162
163 function setObject( value ) {
164
165 object = value;
166
167 normalMatrix.getNormalMatrix( object.matrixWorld );
168
169 normals.length = 0;
170 colors.length = 0;
171 uvs.length = 0;
172
173 }
174
175 function projectVertex( vertex ) {
176
177 var position = vertex.position;
178 var positionWorld = vertex.positionWorld;
179 var positionScreen = vertex.positionScreen;
180
181 positionWorld.copy( position ).applyMatrix4( _modelMatrix );
182 positionScreen.copy( positionWorld ).applyMatrix4( _viewProjectionMatrix );
183
184 var invW = 1 / positionScreen.w;
185
186 positionScreen.x *= invW;
187 positionScreen.y *= invW;
188 positionScreen.z *= invW;
189
190 vertex.visible = positionScreen.x >= - 1 && positionScreen.x <= 1 &&
191 positionScreen.y >= - 1 && positionScreen.y <= 1 &&
192 positionScreen.z >= - 1 && positionScreen.z <= 1;
193
194 }
195
196 function pushVertex( x, y, z ) {
197
198 _vertex = getNextVertexInPool();
199 _vertex.position.set( x, y, z );
200
201 projectVertex( _vertex );
202
203 }
204
205 function pushNormal( x, y, z ) {
206
207 normals.push( x, y, z );
208
209 }
210
211 function pushColor( r, g, b ) {
212
213 colors.push( r, g, b );
214
215 }
216
217 function pushUv( x, y ) {
218
219 uvs.push( x, y );
220
221 }
222
223 function checkTriangleVisibility( v1, v2, v3 ) {
224
225 if ( v1.visible === true || v2.visible === true || v3.visible === true ) return true;
226
227 _points3[ 0 ] = v1.positionScreen;
228 _points3[ 1 ] = v2.positionScreen;
229 _points3[ 2 ] = v3.positionScreen;
230
231 return _clipBox.intersectsBox( _boundingBox.setFromPoints( _points3 ) );
232
233 }
234
235 function checkBackfaceCulling( v1, v2, v3 ) {
236
237 return ( ( v3.positionScreen.x - v1.positionScreen.x ) *
238 ( v2.positionScreen.y - v1.positionScreen.y ) -
239 ( v3.positionScreen.y - v1.positionScreen.y ) *
240 ( v2.positionScreen.x - v1.positionScreen.x ) ) < 0;
241
242 }
243
244 function pushLine( a, b ) {
245
246 var v1 = _vertexPool[ a ];
247 var v2 = _vertexPool[ b ];
248
249 // Clip
250
251 v1.positionScreen.copy( v1.position ).applyMatrix4( _modelViewProjectionMatrix );
252 v2.positionScreen.copy( v2.position ).applyMatrix4( _modelViewProjectionMatrix );
253
254 if ( clipLine( v1.positionScreen, v2.positionScreen ) === true ) {
255
256 // Perform the perspective divide
257 v1.positionScreen.multiplyScalar( 1 / v1.positionScreen.w );
258 v2.positionScreen.multiplyScalar( 1 / v2.positionScreen.w );
259
260 _line = getNextLineInPool();
261 _line.id = object.id;
262 _line.v1.copy( v1 );
263 _line.v2.copy( v2 );
264 _line.z = Math.max( v1.positionScreen.z, v2.positionScreen.z );
265 _line.renderOrder = object.renderOrder;
266
267 _line.material = object.material;
268
269 if ( object.material.vertexColors === THREE.VertexColors ) {
270
271 _line.vertexColors[ 0 ].fromArray( colors, a * 3 );
272 _line.vertexColors[ 1 ].fromArray( colors, b * 3 );
273
274 }
275
276 _renderData.elements.push( _line );
277
278 }
279
280 }
281
282 function pushTriangle( a, b, c, material ) {
283
284 var v1 = _vertexPool[ a ];
285 var v2 = _vertexPool[ b ];
286 var v3 = _vertexPool[ c ];
287
288 if ( checkTriangleVisibility( v1, v2, v3 ) === false ) return;
289
290 if ( material.side === THREE.DoubleSide || checkBackfaceCulling( v1, v2, v3 ) === true ) {
291
292 _face = getNextFaceInPool();
293
294 _face.id = object.id;
295 _face.v1.copy( v1 );
296 _face.v2.copy( v2 );
297 _face.v3.copy( v3 );
298 _face.z = ( v1.positionScreen.z + v2.positionScreen.z + v3.positionScreen.z ) / 3;
299 _face.renderOrder = object.renderOrder;
300
301 // face normal
302 _vector3.subVectors( v3.position, v2.position );
303 _vector4.subVectors( v1.position, v2.position );
304 _vector3.cross( _vector4 );
305 _face.normalModel.copy( _vector3 );
306 _face.normalModel.applyMatrix3( normalMatrix ).normalize();
307
308 for ( var i = 0; i < 3; i ++ ) {
309
310 var normal = _face.vertexNormalsModel[ i ];
311 normal.fromArray( normals, arguments[ i ] * 3 );
312 normal.applyMatrix3( normalMatrix ).normalize();
313
314 var uv = _face.uvs[ i ];
315 uv.fromArray( uvs, arguments[ i ] * 2 );
316
317 }
318
319 _face.vertexNormalsLength = 3;
320
321 _face.material = material;
322
323 if ( material.vertexColors === THREE.FaceColors || material.vertexColors === THREE.VertexColors ) {
324
325 _face.color.fromArray( colors, a * 3 );
326
327 }
328
329 _renderData.elements.push( _face );
330
331 }
332
333 }
334
335 return {
336 setObject: setObject,
337 projectVertex: projectVertex,
338 checkTriangleVisibility: checkTriangleVisibility,
339 checkBackfaceCulling: checkBackfaceCulling,
340 pushVertex: pushVertex,
341 pushNormal: pushNormal,
342 pushColor: pushColor,
343 pushUv: pushUv,
344 pushLine: pushLine,
345 pushTriangle: pushTriangle
346 };
347
348 };
349
350 var renderList = new RenderList();
351
352 function projectObject( object ) {
353
354 if ( object.visible === false ) return;
355
356 if ( object instanceof THREE.Light ) {
357
358 _renderData.lights.push( object );
359
360 } else if ( object instanceof THREE.Mesh || object instanceof THREE.Line || object instanceof THREE.Points ) {
361
362 if ( object.material.visible === false ) return;
363 if ( object.frustumCulled === true && _frustum.intersectsObject( object ) === false ) return;
364
365 addObject( object );
366
367 } else if ( object instanceof THREE.Sprite ) {
368
369 if ( object.material.visible === false ) return;
370 if ( object.frustumCulled === true && _frustum.intersectsSprite( object ) === false ) return;
371
372 addObject( object );
373
374 }
375
376 var children = object.children;
377
378 for ( var i = 0, l = children.length; i < l; i ++ ) {
379
380 projectObject( children[ i ] );
381
382 }
383
384 }
385
386 function addObject( object ) {
387
388 _object = getNextObjectInPool();
389 _object.id = object.id;
390 _object.object = object;
391
392 _vector3.setFromMatrixPosition( object.matrixWorld );
393 _vector3.applyMatrix4( _viewProjectionMatrix );
394 _object.z = _vector3.z;
395 _object.renderOrder = object.renderOrder;
396
397 _renderData.objects.push( _object );
398
399 }
400
401 this.projectScene = function ( scene, camera, sortObjects, sortElements ) {
402
403 _faceCount = 0;
404 _lineCount = 0;
405 _spriteCount = 0;
406
407 _renderData.elements.length = 0;
408
409 if ( scene.autoUpdate === true ) scene.updateMatrixWorld();
410 if ( camera.parent === null ) camera.updateMatrixWorld();
411
412 _viewMatrix.copy( camera.matrixWorldInverse );
413 _viewProjectionMatrix.multiplyMatrices( camera.projectionMatrix, _viewMatrix );
414
415 _frustum.setFromMatrix( _viewProjectionMatrix );
416
417 //
418
419 _objectCount = 0;
420
421 _renderData.objects.length = 0;
422 _renderData.lights.length = 0;
423
424 projectObject( scene );
425
426 if ( sortObjects === true ) {
427
428 _renderData.objects.sort( painterSort );
429
430 }
431
432 //
433
434 var objects = _renderData.objects;
435
436 for ( var o = 0, ol = objects.length; o < ol; o ++ ) {
437
438 var object = objects[ o ].object;
439 var geometry = object.geometry;
440
441 renderList.setObject( object );
442
443 _modelMatrix = object.matrixWorld;
444
445 _vertexCount = 0;
446
447 if ( object instanceof THREE.Mesh ) {
448
449 if ( geometry instanceof THREE.BufferGeometry ) {
450
451 var material = object.material;
452
453 var isMultiMaterial = Array.isArray( material );
454
455 var attributes = geometry.attributes;
456 var groups = geometry.groups;
457
458 if ( attributes.position === undefined ) continue;
459
460 var positions = attributes.position.array;
461
462 for ( var i = 0, l = positions.length; i < l; i += 3 ) {
463
464 var x = positions[ i ];
465 var y = positions[ i + 1 ];
466 var z = positions[ i + 2 ];
467
468 if ( material.morphTargets === true ) {
469
470 var morphTargets = geometry.morphAttributes.position;
471 var morphTargetsRelative = geometry.morphTargetsRelative;
472 var morphInfluences = object.morphTargetInfluences;
473
474 for ( var t = 0, tl = morphTargets.length; t < tl; t ++ ) {
475
476 var influence = morphInfluences[ t ];
477
478 if ( influence === 0 ) continue;
479
480 var target = morphTargets[ t ];
481
482 if ( morphTargetsRelative ) {
483
484 x += target.getX( i / 3 ) * influence;
485 y += target.getY( i / 3 ) * influence;
486 z += target.getZ( i / 3 ) * influence;
487
488 } else {
489
490 x += ( target.getX( i / 3 ) - positions[ i ] ) * influence;
491 y += ( target.getY( i / 3 ) - positions[ i + 1 ] ) * influence;
492 z += ( target.getZ( i / 3 ) - positions[ i + 2 ] ) * influence;
493
494 }
495
496 }
497
498 }
499
500 renderList.pushVertex( x, y, z );
501
502 }
503
504 if ( attributes.normal !== undefined ) {
505
506 var normals = attributes.normal.array;
507
508 for ( var i = 0, l = normals.length; i < l; i += 3 ) {
509
510 renderList.pushNormal( normals[ i ], normals[ i + 1 ], normals[ i + 2 ] );
511
512 }
513
514 }
515
516 if ( attributes.color !== undefined ) {
517
518 var colors = attributes.color.array;
519
520 for ( var i = 0, l = colors.length; i < l; i += 3 ) {
521
522 renderList.pushColor( colors[ i ], colors[ i + 1 ], colors[ i + 2 ] );
523
524 }
525
526 }
527
528 if ( attributes.uv !== undefined ) {
529
530 var uvs = attributes.uv.array;
531
532 for ( var i = 0, l = uvs.length; i < l; i += 2 ) {
533
534 renderList.pushUv( uvs[ i ], uvs[ i + 1 ] );
535
536 }
537
538 }
539
540 if ( geometry.index !== null ) {
541
542 var indices = geometry.index.array;
543
544 if ( groups.length > 0 ) {
545
546 for ( var g = 0; g < groups.length; g ++ ) {
547
548 var group = groups[ g ];
549
550 material = isMultiMaterial === true
551 ? object.material[ group.materialIndex ]
552 : object.material;
553
554 if ( material === undefined ) continue;
555
556 for ( var i = group.start, l = group.start + group.count; i < l; i += 3 ) {
557
558 renderList.pushTriangle( indices[ i ], indices[ i + 1 ], indices[ i + 2 ], material );
559
560 }
561
562 }
563
564 } else {
565
566 for ( var i = 0, l = indices.length; i < l; i += 3 ) {
567
568 renderList.pushTriangle( indices[ i ], indices[ i + 1 ], indices[ i + 2 ], material );
569
570 }
571
572 }
573
574 } else {
575
576 if ( groups.length > 0 ) {
577
578 for ( var g = 0; g < groups.length; g ++ ) {
579
580 var group = groups[ g ];
581
582 material = isMultiMaterial === true
583 ? object.material[ group.materialIndex ]
584 : object.material;
585
586 if ( material === undefined ) continue;
587
588 for ( var i = group.start, l = group.start + group.count; i < l; i += 3 ) {
589
590 renderList.pushTriangle( i, i + 1, i + 2, material );
591
592 }
593
594 }
595
596 } else {
597
598 for ( var i = 0, l = positions.length / 3; i < l; i += 3 ) {
599
600 renderList.pushTriangle( i, i + 1, i + 2, material );
601
602 }
603
604 }
605
606 }
607
608 } else if ( geometry instanceof THREE.Geometry ) {
609
610 var vertices = geometry.vertices;
611 var faces = geometry.faces;
612 var faceVertexUvs = geometry.faceVertexUvs[ 0 ];
613
614 _normalMatrix.getNormalMatrix( _modelMatrix );
615
616 var material = object.material;
617
618 var isMultiMaterial = Array.isArray( material );
619
620 for ( var v = 0, vl = vertices.length; v < vl; v ++ ) {
621
622 var vertex = vertices[ v ];
623
624 _vector3.copy( vertex );
625
626 if ( material.morphTargets === true ) {
627
628 var morphTargets = geometry.morphTargets;
629 var morphInfluences = object.morphTargetInfluences;
630
631 for ( var t = 0, tl = morphTargets.length; t < tl; t ++ ) {
632
633 var influence = morphInfluences[ t ];
634
635 if ( influence === 0 ) continue;
636
637 var target = morphTargets[ t ];
638 var targetVertex = target.vertices[ v ];
639
640 _vector3.x += ( targetVertex.x - vertex.x ) * influence;
641 _vector3.y += ( targetVertex.y - vertex.y ) * influence;
642 _vector3.z += ( targetVertex.z - vertex.z ) * influence;
643
644 }
645
646 }
647
648 renderList.pushVertex( _vector3.x, _vector3.y, _vector3.z );
649
650 }
651
652 for ( var f = 0, fl = faces.length; f < fl; f ++ ) {
653
654 var face = faces[ f ];
655
656 material = isMultiMaterial === true
657 ? object.material[ face.materialIndex ]
658 : object.material;
659
660 if ( material === undefined ) continue;
661
662 var side = material.side;
663
664 var v1 = _vertexPool[ face.a ];
665 var v2 = _vertexPool[ face.b ];
666 var v3 = _vertexPool[ face.c ];
667
668 if ( renderList.checkTriangleVisibility( v1, v2, v3 ) === false ) continue;
669
670 var visible = renderList.checkBackfaceCulling( v1, v2, v3 );
671
672 if ( side !== THREE.DoubleSide ) {
673
674 if ( side === THREE.FrontSide && visible === false ) continue;
675 if ( side === THREE.BackSide && visible === true ) continue;
676
677 }
678
679 _face = getNextFaceInPool();
680
681 _face.id = object.id;
682 _face.v1.copy( v1 );
683 _face.v2.copy( v2 );
684 _face.v3.copy( v3 );
685
686 _face.normalModel.copy( face.normal );
687
688 if ( visible === false && ( side === THREE.BackSide || side === THREE.DoubleSide ) ) {
689
690 _face.normalModel.negate();
691
692 }
693
694 _face.normalModel.applyMatrix3( _normalMatrix ).normalize();
695
696 var faceVertexNormals = face.vertexNormals;
697
698 for ( var n = 0, nl = Math.min( faceVertexNormals.length, 3 ); n < nl; n ++ ) {
699
700 var normalModel = _face.vertexNormalsModel[ n ];
701 normalModel.copy( faceVertexNormals[ n ] );
702
703 if ( visible === false && ( side === THREE.BackSide || side === THREE.DoubleSide ) ) {
704
705 normalModel.negate();
706
707 }
708
709 normalModel.applyMatrix3( _normalMatrix ).normalize();
710
711 }
712
713 _face.vertexNormalsLength = faceVertexNormals.length;
714
715 var vertexUvs = faceVertexUvs[ f ];
716
717 if ( vertexUvs !== undefined ) {
718
719 for ( var u = 0; u < 3; u ++ ) {
720
721 _face.uvs[ u ].copy( vertexUvs[ u ] );
722
723 }
724
725 }
726
727 _face.color = face.color;
728 _face.material = material;
729
730 _face.z = ( v1.positionScreen.z + v2.positionScreen.z + v3.positionScreen.z ) / 3;
731 _face.renderOrder = object.renderOrder;
732
733 _renderData.elements.push( _face );
734
735 }
736
737 }
738
739 } else if ( object instanceof THREE.Line ) {
740
741 _modelViewProjectionMatrix.multiplyMatrices( _viewProjectionMatrix, _modelMatrix );
742
743 if ( geometry instanceof THREE.BufferGeometry ) {
744
745 var attributes = geometry.attributes;
746
747 if ( attributes.position !== undefined ) {
748
749 var positions = attributes.position.array;
750
751 for ( var i = 0, l = positions.length; i < l; i += 3 ) {
752
753 renderList.pushVertex( positions[ i ], positions[ i + 1 ], positions[ i + 2 ] );
754
755 }
756
757 if ( attributes.color !== undefined ) {
758
759 var colors = attributes.color.array;
760
761 for ( var i = 0, l = colors.length; i < l; i += 3 ) {
762
763 renderList.pushColor( colors[ i ], colors[ i + 1 ], colors[ i + 2 ] );
764
765 }
766
767 }
768
769 if ( geometry.index !== null ) {
770
771 var indices = geometry.index.array;
772
773 for ( var i = 0, l = indices.length; i < l; i += 2 ) {
774
775 renderList.pushLine( indices[ i ], indices[ i + 1 ] );
776
777 }
778
779 } else {
780
781 var step = object instanceof THREE.LineSegments ? 2 : 1;
782
783 for ( var i = 0, l = ( positions.length / 3 ) - 1; i < l; i += step ) {
784
785 renderList.pushLine( i, i + 1 );
786
787 }
788
789 }
790
791 }
792
793 } else if ( geometry instanceof THREE.Geometry ) {
794
795 var vertices = object.geometry.vertices;
796
797 if ( vertices.length === 0 ) continue;
798
799 v1 = getNextVertexInPool();
800 v1.positionScreen.copy( vertices[ 0 ] ).applyMatrix4( _modelViewProjectionMatrix );
801
802 var step = object instanceof THREE.LineSegments ? 2 : 1;
803
804 for ( var v = 1, vl = vertices.length; v < vl; v ++ ) {
805
806 v1 = getNextVertexInPool();
807 v1.positionScreen.copy( vertices[ v ] ).applyMatrix4( _modelViewProjectionMatrix );
808
809 if ( ( v + 1 ) % step > 0 ) continue;
810
811 v2 = _vertexPool[ _vertexCount - 2 ];
812
813 _clippedVertex1PositionScreen.copy( v1.positionScreen );
814 _clippedVertex2PositionScreen.copy( v2.positionScreen );
815
816 if ( clipLine( _clippedVertex1PositionScreen, _clippedVertex2PositionScreen ) === true ) {
817
818 // Perform the perspective divide
819 _clippedVertex1PositionScreen.multiplyScalar( 1 / _clippedVertex1PositionScreen.w );
820 _clippedVertex2PositionScreen.multiplyScalar( 1 / _clippedVertex2PositionScreen.w );
821
822 _line = getNextLineInPool();
823
824 _line.id = object.id;
825 _line.v1.positionScreen.copy( _clippedVertex1PositionScreen );
826 _line.v2.positionScreen.copy( _clippedVertex2PositionScreen );
827
828 _line.z = Math.max( _clippedVertex1PositionScreen.z, _clippedVertex2PositionScreen.z );
829 _line.renderOrder = object.renderOrder;
830
831 _line.material = object.material;
832
833 if ( object.material.vertexColors === THREE.VertexColors ) {
834
835 _line.vertexColors[ 0 ].copy( object.geometry.colors[ v ] );
836 _line.vertexColors[ 1 ].copy( object.geometry.colors[ v - 1 ] );
837
838 }
839
840 _renderData.elements.push( _line );
841
842 }
843
844 }
845
846 }
847
848 } else if ( object instanceof THREE.Points ) {
849
850 _modelViewProjectionMatrix.multiplyMatrices( _viewProjectionMatrix, _modelMatrix );
851
852 if ( geometry instanceof THREE.Geometry ) {
853
854 var vertices = object.geometry.vertices;
855
856 for ( var v = 0, vl = vertices.length; v < vl; v ++ ) {
857
858 var vertex = vertices[ v ];
859
860 _vector4.set( vertex.x, vertex.y, vertex.z, 1 );
861 _vector4.applyMatrix4( _modelViewProjectionMatrix );
862
863 pushPoint( _vector4, object, camera );
864
865 }
866
867 } else if ( geometry instanceof THREE.BufferGeometry ) {
868
869 var attributes = geometry.attributes;
870
871 if ( attributes.position !== undefined ) {
872
873 var positions = attributes.position.array;
874
875 for ( var i = 0, l = positions.length; i < l; i += 3 ) {
876
877 _vector4.set( positions[ i ], positions[ i + 1 ], positions[ i + 2 ], 1 );
878 _vector4.applyMatrix4( _modelViewProjectionMatrix );
879
880 pushPoint( _vector4, object, camera );
881
882 }
883
884 }
885
886 }
887
888 } else if ( object instanceof THREE.Sprite ) {
889
890 object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
891 _vector4.set( _modelMatrix.elements[ 12 ], _modelMatrix.elements[ 13 ], _modelMatrix.elements[ 14 ], 1 );
892 _vector4.applyMatrix4( _viewProjectionMatrix );
893
894 pushPoint( _vector4, object, camera );
895
896 }
897
898 }
899
900 if ( sortElements === true ) {
901
902 _renderData.elements.sort( painterSort );
903
904 }
905
906 return _renderData;
907
908 };
909
910 function pushPoint( _vector4, object, camera ) {
911
912 var invW = 1 / _vector4.w;
913
914 _vector4.z *= invW;
915
916 if ( _vector4.z >= - 1 && _vector4.z <= 1 ) {
917
918 _sprite = getNextSpriteInPool();
919 _sprite.id = object.id;
920 _sprite.x = _vector4.x * invW;
921 _sprite.y = _vector4.y * invW;
922 _sprite.z = _vector4.z;
923 _sprite.renderOrder = object.renderOrder;
924 _sprite.object = object;
925
926 _sprite.rotation = object.rotation;
927
928 _sprite.scale.x = object.scale.x * Math.abs( _sprite.x - ( _vector4.x + camera.projectionMatrix.elements[ 0 ] ) / ( _vector4.w + camera.projectionMatrix.elements[ 12 ] ) );
929 _sprite.scale.y = object.scale.y * Math.abs( _sprite.y - ( _vector4.y + camera.projectionMatrix.elements[ 5 ] ) / ( _vector4.w + camera.projectionMatrix.elements[ 13 ] ) );
930
931 _sprite.material = object.material;
932
933 _renderData.elements.push( _sprite );
934
935 }
936
937 }
938
939 // Pools
940
941 function getNextObjectInPool() {
942
943 if ( _objectCount === _objectPoolLength ) {
944
945 var object = new THREE.RenderableObject();
946 _objectPool.push( object );
947 _objectPoolLength ++;
948 _objectCount ++;
949 return object;
950
951 }
952
953 return _objectPool[ _objectCount ++ ];
954
955 }
956
957 function getNextVertexInPool() {
958
959 if ( _vertexCount === _vertexPoolLength ) {
960
961 var vertex = new THREE.RenderableVertex();
962 _vertexPool.push( vertex );
963 _vertexPoolLength ++;
964 _vertexCount ++;
965 return vertex;
966
967 }
968
969 return _vertexPool[ _vertexCount ++ ];
970
971 }
972
973 function getNextFaceInPool() {
974
975 if ( _faceCount === _facePoolLength ) {
976
977 var face = new THREE.RenderableFace();
978 _facePool.push( face );
979 _facePoolLength ++;
980 _faceCount ++;
981 return face;
982
983 }
984
985 return _facePool[ _faceCount ++ ];
986
987
988 }
989
990 function getNextLineInPool() {
991
992 if ( _lineCount === _linePoolLength ) {
993
994 var line = new THREE.RenderableLine();
995 _linePool.push( line );
996 _linePoolLength ++;
997 _lineCount ++;
998 return line;
999
1000 }
1001
1002 return _linePool[ _lineCount ++ ];
1003
1004 }
1005
1006 function getNextSpriteInPool() {
1007
1008 if ( _spriteCount === _spritePoolLength ) {
1009
1010 var sprite = new THREE.RenderableSprite();
1011 _spritePool.push( sprite );
1012 _spritePoolLength ++;
1013 _spriteCount ++;
1014 return sprite;
1015
1016 }
1017
1018 return _spritePool[ _spriteCount ++ ];
1019
1020 }
1021
1022 //
1023
1024 function painterSort( a, b ) {
1025
1026 if ( a.renderOrder !== b.renderOrder ) {
1027
1028 return a.renderOrder - b.renderOrder;
1029
1030 } else if ( a.z !== b.z ) {
1031
1032 return b.z - a.z;
1033
1034 } else if ( a.id !== b.id ) {
1035
1036 return a.id - b.id;
1037
1038 } else {
1039
1040 return 0;
1041
1042 }
1043
1044 }
1045
1046 function clipLine( s1, s2 ) {
1047
1048 var alpha1 = 0, alpha2 = 1,
1049
1050 // Calculate the boundary coordinate of each vertex for the near and far clip planes,
1051 // Z = -1 and Z = +1, respectively.
1052
1053 bc1near = s1.z + s1.w,
1054 bc2near = s2.z + s2.w,
1055 bc1far = - s1.z + s1.w,
1056 bc2far = - s2.z + s2.w;
1057
1058 if ( bc1near >= 0 && bc2near >= 0 && bc1far >= 0 && bc2far >= 0 ) {
1059
1060 // Both vertices lie entirely within all clip planes.
1061 return true;
1062
1063 } else if ( ( bc1near < 0 && bc2near < 0 ) || ( bc1far < 0 && bc2far < 0 ) ) {
1064
1065 // Both vertices lie entirely outside one of the clip planes.
1066 return false;
1067
1068 } else {
1069
1070 // The line segment spans at least one clip plane.
1071
1072 if ( bc1near < 0 ) {
1073
1074 // v1 lies outside the near plane, v2 inside
1075 alpha1 = Math.max( alpha1, bc1near / ( bc1near - bc2near ) );
1076
1077 } else if ( bc2near < 0 ) {
1078
1079 // v2 lies outside the near plane, v1 inside
1080 alpha2 = Math.min( alpha2, bc1near / ( bc1near - bc2near ) );
1081
1082 }
1083
1084 if ( bc1far < 0 ) {
1085
1086 // v1 lies outside the far plane, v2 inside
1087 alpha1 = Math.max( alpha1, bc1far / ( bc1far - bc2far ) );
1088
1089 } else if ( bc2far < 0 ) {
1090
1091 // v2 lies outside the far plane, v2 inside
1092 alpha2 = Math.min( alpha2, bc1far / ( bc1far - bc2far ) );
1093
1094 }
1095
1096 if ( alpha2 < alpha1 ) {
1097
1098 // The line segment spans two boundaries, but is outside both of them.
1099 // (This can't happen when we're only clipping against just near/far but good
1100 // to leave the check here for future usage if other clip planes are added.)
1101 return false;
1102
1103 } else {
1104
1105 // Update the s1 and s2 vertices to match the clipped line segment.
1106 s1.lerp( s2, alpha1 );
1107 s2.lerp( s1, 1 - alpha2 );
1108
1109 return true;
1110
1111 }
1112
1113 }
1114
1115 }
1116
1117};