2 if ( typeof define ===
"function" && define.amd ) {
3 define( [
'threejs' ], factory );
4 }
else if (typeof exports ===
'object' && typeof module !==
'undefined') {
5 factory(require(
"three"), exports);
7 if (typeof THREE ==
'undefined')
8 throw new Error(
'THREE is not defined',
'ThreeCSG.js');
9 ThreeBSP = factory(THREE);
11 } (
function(THREE, ThreeBSP) {
15 if (!ThreeBSP) ThreeBSP = {};
23 ThreeBSP.Geometry =
function( geometry, transfer_matrix, nodeid, flippedMesh ) {
26 if ( geometry instanceof THREE.Geometry ) {
28 }
else if ( geometry instanceof THREE.Mesh ) {
30 geometry.updateMatrix();
31 transfer_matrix = this.matrix = geometry.matrix.clone();
32 geometry = geometry.geometry;
33 }
else if ( geometry instanceof ThreeBSP.Node ) {
37 }
else if ( geometry instanceof THREE.BufferGeometry ) {
38 var pos_buf = geometry.getAttribute(
'position').array,
39 norm_buf = geometry.getAttribute(
'normal').array,
40 polygons = [], polygon, vert1, vert2, vert3;
42 for (var i=0; i < pos_buf.length; i+=9) {
43 polygon =
new ThreeBSP.Polygon;
45 vert1 =
new ThreeBSP.Vertex( pos_buf[i], pos_buf[i+1], pos_buf[i+2], norm_buf[i], norm_buf[i+1], norm_buf[i+2]);
46 if (transfer_matrix) vert1.applyMatrix4(transfer_matrix);
48 vert2 =
new ThreeBSP.Vertex( pos_buf[i+3], pos_buf[i+4], pos_buf[i+5], norm_buf[i+3], norm_buf[i+4], norm_buf[i+5]);
49 if (transfer_matrix) vert2.applyMatrix4(transfer_matrix);
51 vert3 =
new ThreeBSP.Vertex( pos_buf[i+6], pos_buf[i+7], pos_buf[i+8], norm_buf[i+6], norm_buf[i+7], norm_buf[i+8]);
52 if (transfer_matrix) vert3.applyMatrix4(transfer_matrix);
54 if (flippedMesh) polygon.vertices.push( vert1, vert3, vert2 );
55 else polygon.vertices.push( vert1, vert2, vert3 );
57 polygon.calculateProperties();
58 polygons.push( polygon );
61 this.tree =
new ThreeBSP.Node( polygons, nodeid );
62 if (nodeid!==undefined) this.maxid = this.tree.maxnodeid;
65 }
else if (geometry.polygons && (geometry.polygons[0] instanceof ThreeBSP.Polygon)) {
66 var polygons = geometry.polygons;
68 for (var i=0;i<polygons.length;++i) {
69 var polygon = polygons[i];
70 if (transfer_matrix) {
71 for (var n=0;n<polygon.vertices.length;++n)
72 polygon.vertices[n].applyMatrix4(transfer_matrix);
75 polygon.calculateProperties();
78 this.tree =
new ThreeBSP.Node( polygons, nodeid );
79 if (nodeid!==undefined) this.maxid = this.tree.maxnodeid;
83 throw 'ThreeBSP: Given geometry is unsupported';
87 nfaces = geometry.faces.length,
88 face, polygon, vertex, normal, useVertexNormals;
90 for (var i = 0; i < nfaces; ++i ) {
91 face = geometry.faces[i];
94 polygon =
new ThreeBSP.Polygon;
96 if ( face instanceof THREE.Face3 ) {
97 useVertexNormals = face.vertexNormals && (face.vertexNormals.length==3);
99 vertex = geometry.vertices[ face.a ];
100 if (useVertexNormals) normal = face.vertexNormals[0];
102 vertex =
new ThreeBSP.Vertex( vertex.x, vertex.y, vertex.z, normal.x, normal.y, normal.z );
103 if (transfer_matrix) vertex.applyMatrix4(transfer_matrix);
104 polygon.vertices.push( vertex );
106 vertex = geometry.vertices[ face.b ];
107 if (useVertexNormals) normal = face.vertexNormals[1];
109 vertex =
new ThreeBSP.Vertex( vertex.x, vertex.y, vertex.z, normal.x, normal.y, normal.z );
110 if (transfer_matrix) vertex.applyMatrix4(transfer_matrix);
111 polygon.vertices.push( vertex );
113 vertex = geometry.vertices[ face.c ];
114 if (useVertexNormals) normal = face.vertexNormals[2];
116 vertex =
new ThreeBSP.Vertex( vertex.x, vertex.y, vertex.z, normal.x, normal.y, normal.z );
117 if (transfer_matrix) vertex.applyMatrix4(transfer_matrix);
118 polygon.vertices.push( vertex );
119 }
else if ( typeof THREE.Face4 ) {
120 useVertexNormals = face.vertexNormals && (face.vertexNormals.length==4);
122 vertex = geometry.vertices[ face.a ];
123 if (useVertexNormals) normal = face.vertexNormals[0];
125 vertex =
new ThreeBSP.Vertex( vertex.x, vertex.y, vertex.z, normal.x, normal.y, normal.z );
126 if (transfer_matrix) vertex.applyMatrix4(transfer_matrix);
127 polygon.vertices.push( vertex );
129 vertex = geometry.vertices[ face.b ];
130 if (useVertexNormals) normal = face.vertexNormals[1];
132 vertex =
new ThreeBSP.Vertex( vertex.x, vertex.y, vertex.z, normal.x, normal.y, normal.z );
133 if (transfer_matrix) vertex.applyMatrix4(transfer_matrix);
134 polygon.vertices.push( vertex );
136 vertex = geometry.vertices[ face.c ];
137 if (useVertexNormals) normal = face.vertexNormals[2];
139 vertex =
new ThreeBSP.Vertex( vertex.x, vertex.y, vertex.z, normal.x, normal.y, normal.z );
140 if (transfer_matrix) vertex.applyMatrix4(transfer_matrix);
141 polygon.vertices.push( vertex );
143 vertex = geometry.vertices[ face.d ];
144 if (useVertexNormals) normal = face.vertexNormals[3];
146 vertex =
new ThreeBSP.Vertex( vertex.x, vertex.y, vertex.z, normal.x, normal.y, normal.z );
147 if (transfer_matrix) vertex.applyMatrix4(transfer_matrix);
148 polygon.vertices.push( vertex );
150 throw 'Invalid face type at index ' + i;
153 polygon.calculateProperties();
154 polygons.push( polygon );
157 this.tree =
new ThreeBSP.Node( polygons, nodeid );
158 if (nodeid!==undefined) this.maxid = this.tree.maxnodeid;
161 ThreeBSP.Geometry.prototype.subtract =
function( other_tree ) {
162 var a = this.tree.clone(),
163 b = other_tree.tree.clone();
171 a.build( b.allPolygons() );
173 a =
new ThreeBSP.Geometry( a );
174 a.matrix = this.matrix;
178 ThreeBSP.Geometry.prototype.union =
function( other_tree ) {
179 var a = this.tree.clone(),
180 b = other_tree.tree.clone();
187 a.build( b.allPolygons() );
188 a =
new ThreeBSP.Geometry( a );
189 a.matrix = this.matrix;
193 ThreeBSP.Geometry.prototype.intersect =
function( other_tree ) {
194 var a = this.tree.clone(),
195 b = other_tree.tree.clone();
202 a.build( b.allPolygons() );
204 a =
new ThreeBSP.Geometry( a );
205 a.matrix = this.matrix;
209 ThreeBSP.Geometry.prototype.tryToCompress =
function(polygons) {
211 if (this.maxid === undefined)
return;
213 var arr = [], parts, foundpair,
214 nreduce = 0, n, len = polygons.length,
218 for (n=0;n<len;++n) {
220 if (p.id === undefined)
continue;
221 if (arr[p.id] === undefined) arr[p.id] = [];
226 for(n=0; n<arr.length; ++n) {
228 if (parts===undefined)
continue;
232 foundpair = (len > 1);
237 for (i1 = 0; i1<len-1; ++i1) {
239 if (!p1 || !p1.parent)
continue;
240 for (i2 = i1+1; i2 < len; ++i2) {
242 if (p2 && (p1.parent === p2.parent) && (p1.nsign === p2.nsign)) {
244 if (p1.nsign !== p1.parent.nsign) p1.parent.flip();
247 parts[i1] = p1.parent;
249 if (p1.parent.vertices.length < 3) console.log(
'something wrong with parent');
259 polygons.splice(0, polygons.length);
261 for(n=0;n<arr.length;++n) {
263 if (parts !== undefined)
264 for (i1=0,len=parts.length; i1<len;++i1)
265 if (parts[i1]) polygons.push(parts[i1]);
271 ThreeBSP.Geometry.prototype.direct_subtract =
function( other_tree ) {
280 a.build( b.collectPolygons([]) );
285 ThreeBSP.Geometry.prototype.direct_union =
function( other_tree ) {
294 a.build( b.collectPolygons([]) );
298 ThreeBSP.Geometry.prototype.direct_intersect =
function( other_tree ) {
307 a.build( b.collectPolygons([]) );
312 ThreeBSP.CreateNormal =
function(axis_name, pos, size) {
315 var vert1, vert2, vert3;
317 if (!size || (size<10000)) size = 10000;
321 vert1 =
new ThreeBSP.Vertex(pos, -3*size, size, 1, 0, 0),
322 vert3 =
new ThreeBSP.Vertex(pos, size, size, 1, 0, 0),
323 vert2 =
new ThreeBSP.Vertex(pos, size, -3*size, 1, 0, 0);
326 vert1 =
new ThreeBSP.Vertex(-3*size, pos, size, 0, 1, 0),
327 vert2 =
new ThreeBSP.Vertex( size, pos, size, 0, 1, 0),
328 vert3 =
new ThreeBSP.Vertex( size, pos, -3*size, 0, 1, 0);
331 vert1 =
new ThreeBSP.Vertex(-3*size, size, pos, 0, 0, 1),
332 vert3 =
new ThreeBSP.Vertex( size, size, pos, 0, 0, 1),
333 vert2 =
new ThreeBSP.Vertex( size, -3*size, pos, 0, 0, 1);
337 var polygon =
new ThreeBSP.Polygon([vert1, vert2, vert3]);
338 polygon.calculateProperties();
340 var node =
new ThreeBSP.Node([polygon]);
342 return new ThreeBSP.Geometry(node);
346 ThreeBSP.Geometry.prototype.cut_from_plane =
function( other_tree) {
359 ThreeBSP.Geometry.prototype.toGeometry =
function() {
361 matrix = this.matrix ?
new THREE.Matrix4().getInverse( this.matrix ) : null,
362 geometry =
new THREE.Geometry(),
363 polygons = this.tree.collectPolygons([]),
364 polygon_count = polygons.length,
365 polygon, polygon_vertice_count,
367 vertex_idx_a, vertex_idx_b, vertex_idx_c,
370 for ( i = 0; i < polygon_count; ++i ) {
371 polygon = polygons[i];
372 polygon_vertice_count = polygon.vertices.length;
374 for ( j = 2; j < polygon_vertice_count; ++j ) {
377 vertex = polygon.vertices[0];
379 vertex =
new THREE.Vector3( vertex.x, vertex.y, vertex.z );
380 if (matrix) vertex.applyMatrix4(matrix);
382 if ( typeof vertice_dict[ vertex.x +
',' + vertex.y +
',' + vertex.z ] !==
'undefined' ) {
383 vertex_idx_a = vertice_dict[ vertex.x +
',' + vertex.y +
',' + vertex.z ];
385 geometry.vertices.push( vertex );
386 vertex_idx_a = vertice_dict[ vertex.x +
',' + vertex.y +
',' + vertex.z ] = geometry.vertices.length - 1;
389 vertex = polygon.vertices[j-1];
391 vertex =
new THREE.Vector3( vertex.x, vertex.y, vertex.z );
392 if (matrix) vertex.applyMatrix4(matrix);
393 if ( typeof vertice_dict[ vertex.x +
',' + vertex.y +
',' + vertex.z ] !==
'undefined' ) {
394 vertex_idx_b = vertice_dict[ vertex.x +
',' + vertex.y +
',' + vertex.z ];
396 geometry.vertices.push( vertex );
397 vertex_idx_b = vertice_dict[ vertex.x +
',' + vertex.y +
',' + vertex.z ] = geometry.vertices.length - 1;
400 vertex = polygon.vertices[j];
402 vertex =
new THREE.Vector3( vertex.x, vertex.y, vertex.z );
403 if (matrix) vertex.applyMatrix4(matrix);
404 if ( typeof vertice_dict[ vertex.x +
',' + vertex.y +
',' + vertex.z ] !==
'undefined' ) {
405 vertex_idx_c = vertice_dict[ vertex.x +
',' + vertex.y +
',' + vertex.z ];
407 geometry.vertices.push( vertex );
408 vertex_idx_c = vertice_dict[ vertex.x +
',' + vertex.y +
',' + vertex.z ] = geometry.vertices.length - 1;
411 face =
new THREE.Face3(
415 new THREE.Vector3( polygon.normal.x, polygon.normal.y, polygon.normal.z )
418 geometry.faces.push( face );
426 ThreeBSP.Geometry.prototype.scale =
function(x,y,z) {
428 var polygons = this.tree.collectPolygons([]);
430 for (var i = 0; i < polygons.length; ++i) {
431 var polygon = polygons[i];
432 for (var k=0; k < polygon.vertices.length; ++k) {
433 var v = polygon.vertices[k];
438 delete polygon.normal;
439 polygon.calculateProperties();
443 ThreeBSP.Geometry.prototype.toPolygons =
function() {
444 var polygons = this.tree.collectPolygons([]);
446 this.tryToCompress(polygons);
448 for (var i = 0; i < polygons.length; ++i ) {
449 delete polygons[i].id;
450 delete polygons[i].parent;
456 ThreeBSP.Geometry.prototype.toBufferGeometry =
function() {
457 return ThreeBSP.CreateBufferGeometry(this.toPolygons());
460 ThreeBSP.CreateBufferGeometry =
function(polygons) {
461 var i, j, polygon_count = polygons.length, buf_size = 0;
463 for ( i = 0; i < polygon_count; ++i )
464 buf_size += (polygons[i].vertices.length - 2) * 9;
466 var positions_buf =
new Float32Array(buf_size),
467 normals_buf =
new Float32Array(buf_size),
470 function CopyVertex(vertex) {
472 positions_buf[iii] = vertex.x;
473 positions_buf[iii+1] = vertex.y;
474 positions_buf[iii+2] = vertex.z;
476 normals_buf[iii] = polygon.nsign * vertex.nx;
477 normals_buf[iii+1] = polygon.nsign * vertex.ny;
478 normals_buf[iii+2] = polygon.nsign * vertex.nz;
482 for ( i = 0; i < polygon_count; ++i ) {
483 polygon = polygons[i];
484 for ( j = 2; j < polygon.vertices.length; ++j ) {
485 CopyVertex(polygon.vertices[0]);
486 CopyVertex(polygon.vertices[j-1]);
487 CopyVertex(polygon.vertices[j]);
491 var geometry =
new THREE.BufferGeometry();
492 geometry.addAttribute(
'position',
new THREE.BufferAttribute( positions_buf, 3 ) );
493 geometry.addAttribute(
'normal',
new THREE.BufferAttribute( normals_buf, 3 ) );
499 ThreeBSP.Geometry.prototype.toMesh =
function( material ) {
500 var geometry = this.toGeometry(),
501 mesh =
new THREE.Mesh( geometry, material );
504 mesh.position.setFromMatrixPosition( this.matrix );
505 mesh.rotation.setFromRotationMatrix( this.matrix );
511 ThreeBSP.Polygon =
function( vertices, normal, w ) {
512 if ( !( vertices instanceof Array ) ) {
516 this.vertices = vertices;
518 if ( vertices.length > 0 ) {
519 this.calculateProperties();
521 this.normal = this.w = undefined;
525 ThreeBSP.Polygon.prototype.copyProperties =
function(parent, more) {
526 this.normal = parent.normal;
528 this.nsign = parent.nsign;
529 if (more && (parent.id !== undefined)) {
531 this.parent = parent;
536 ThreeBSP.Polygon.prototype.calculateProperties =
function() {
537 if (this.normal)
return;
539 var a = this.vertices[0],
540 b = this.vertices[1],
541 c = this.vertices[2];
545 this.normal = b.clone().subtract( a ).cross(
546 c.clone().subtract( a )
549 this.w = this.normal.clone().dot( a );
553 ThreeBSP.Polygon.prototype.clone =
function() {
554 var vertice_count = this.vertices.length,
555 polygon =
new ThreeBSP.Polygon;
557 for (var i = 0; i < vertice_count; ++i )
558 polygon.vertices.push(
this.vertices[i].clone() );
560 return polygon.copyProperties(
this);
563 ThreeBSP.Polygon.prototype.flip =
function() {
571 this.vertices.reverse();
576 ThreeBSP.Polygon.prototype.classifyVertex =
function( vertex ) {
577 var side_value = this.nsign * (this.normal.dot( vertex ) - this.w);
579 if ( side_value < -EPSILON )
return BACK;
580 if ( side_value > EPSILON )
return FRONT;
584 ThreeBSP.Polygon.prototype.classifySide =
function( polygon ) {
585 var i, classification,
586 num_positive = 0, num_negative = 0,
587 vertice_count = polygon.vertices.length;
589 for ( i = 0; i < vertice_count; ++i ) {
590 classification = this.classifyVertex( polygon.vertices[i] );
591 if ( classification === FRONT ) {
593 }
else if ( classification === BACK ) {
598 if ( num_positive > 0 && num_negative === 0 )
return FRONT;
599 if ( num_positive === 0 && num_negative > 0 )
return BACK;
600 if ( num_positive === 0 && num_negative === 0 )
return COPLANAR;
604 ThreeBSP.Polygon.prototype.splitPolygon =
function( polygon, coplanar_front, coplanar_back, front, back ) {
605 var classification = this.classifySide( polygon );
607 if ( classification === COPLANAR ) {
609 ( (this.nsign * polygon.nsign * this.normal.dot( polygon.normal ) > 0) ? coplanar_front : coplanar_back ).push( polygon );
611 }
else if ( classification === FRONT ) {
613 front.push( polygon );
615 }
else if ( classification === BACK ) {
617 back.push( polygon );
621 var vertice_count = polygon.vertices.length,
625 i, j, ti, tj, vi, vj,
629 for ( i = 0; i < vertice_count; ++i ) {
631 j = (i + 1) % vertice_count;
632 vi = polygon.vertices[i];
633 vj = polygon.vertices[j];
634 ti = this.classifyVertex( vi );
635 tj = this.classifyVertex( vj );
637 if ( ti != BACK ) f.push( vi );
638 if ( ti != FRONT ) b.push( vi );
639 if ( (ti | tj) === SPANNING ) {
643 t = (this.w - (nnx*vi.x + nny*vi.y + nnz*vi.z)) / (nnx*(vj.x-vi.x) + nny*(vj.y-vi.y) + nnz*(vj.z-vi.z));
645 v = vi.interpolate( vj, t );
653 if ( f.length >= 3 ) front.push(
new ThreeBSP.Polygon( f ).copyProperties(polygon,
true) );
654 if ( b.length >= 3 ) back.push(
new ThreeBSP.Polygon( b ).copyProperties(polygon,
true) );
658 ThreeBSP.Vertex =
function(x, y, z, nx, ny, nz) {
667 ThreeBSP.Vertex.prototype.setnormal =
function ( nx, ny, nz ) {
673 ThreeBSP.Vertex.prototype.clone =
function() {
674 return new ThreeBSP.Vertex( this.x, this.y, this.z, this.nx, this.ny, this.nz);
677 ThreeBSP.Vertex.prototype.add =
function( vertex ) {
684 ThreeBSP.Vertex.prototype.subtract =
function( vertex ) {
691 ThreeBSP.Vertex.prototype.multiplyScalar =
function( scalar ) {
698 ThreeBSP.Vertex.prototype.cross =
function( vertex ) {
703 this.x = y * vertex.z - z * vertex.y;
704 this.y = z * vertex.x - x * vertex.z;
705 this.z = x * vertex.y - y * vertex.x;
710 ThreeBSP.Vertex.prototype.normalize =
function() {
711 var length = Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z );
720 ThreeBSP.Vertex.prototype.dot =
function( vertex ) {
721 return this.x*vertex.x + this.y*vertex.y + this.z*vertex.z;
724 ThreeBSP.Vertex.prototype.diff =
function( vertex ) {
725 var dx = (this.x - vertex.x),
726 dy = (this.y - vertex.y),
727 dz = (this.z - vertex.z),
728 len2 = this.x*this.x + this.y*this.y + this.z*this.z;
730 return (dx*dx + dy*dy + dz*dz) / (len2>0 ? len2 : 1e-10);
754 ThreeBSP.Vertex.prototype.interpolate =
function( a, t ) {
756 return new ThreeBSP.Vertex(this.x*t1 + a.x*t,
this.y*t1 + a.y*t,
this.z*t1 + a.z*t,
757 this.nx*t1 + a.nx*t,
this.ny*t1 + a.ny*t,
this.nz*t1 + a.nz*t);
760 ThreeBSP.Vertex.prototype.applyMatrix4 =
function ( m ) {
764 var x = this.x, y = this.y, z = this.z, e = m.elements;
766 this.x = e[0] * x + e[4] * y + e[8] * z + e[12];
767 this.y = e[1] * x + e[5] * y + e[9] * z + e[13];
768 this.z = e[2] * x + e[6] * y + e[10] * z + e[14];
770 x = this.nx; y = this.ny; z = this.nz;
772 this.nx = e[0] * x + e[4] * y + e[8] * z;
773 this.ny = e[1] * x + e[5] * y + e[9] * z;
774 this.nz = e[2] * x + e[6] * y + e[10] * z;
781 ThreeBSP.Node =
function( polygons, nodeid ) {
783 this.front = this.back = undefined;
785 if ( !(polygons instanceof Array) || polygons.length === 0 )
return;
787 this.divider = polygons[0].clone();
789 var polygon_count = polygons.length,
790 front = [], back = [];
792 for (var i = 0; i < polygon_count; ++i ) {
793 if (nodeid!==undefined) {
794 polygons[i].id = nodeid++;
795 delete polygons[i].parent;
798 this.divider.splitPolygon( polygons[i], this.polygons, this.polygons, front, back );
801 if (nodeid !== undefined) this.maxnodeid = nodeid;
803 if ( front.length > 0 )
804 this.front =
new ThreeBSP.Node( front );
806 if ( back.length > 0 )
807 this.back =
new ThreeBSP.Node( back );
810 ThreeBSP.Node.isConvex =
function( polygons ) {
811 var i, j, len = polygons.length;
812 for ( i = 0; i < len; ++i )
813 for ( j = 0; j < len; ++j )
814 if ( i !== j && polygons[i].classifySide( polygons[j] ) !== BACK )
return false;
818 ThreeBSP.Node.prototype.build =
function( polygons ) {
819 var polygon_count = polygons.length,
820 front = [], back = [];
823 this.divider = polygons[0].clone();
825 for (var i = 0; i < polygon_count; ++i )
826 this.divider.splitPolygon( polygons[i],
this.polygons,
this.polygons, front, back );
828 if ( front.length > 0 ) {
829 if ( !this.front ) this.front =
new ThreeBSP.Node();
830 this.front.build( front );
833 if ( back.length > 0 ) {
834 if ( !this.back ) this.back =
new ThreeBSP.Node();
835 this.back.build( back );
839 ThreeBSP.Node.prototype.collectPolygons =
function(arr) {
840 var len = this.polygons.length;
841 for (var i=0;i<len;++i) arr.push(
this.polygons[i]);
842 if ( this.front ) this.front.collectPolygons(arr);
843 if ( this.back ) this.back.collectPolygons(arr);
847 ThreeBSP.Node.prototype.allPolygons =
function() {
848 var polygons = this.polygons.slice();
849 if ( this.front ) polygons = polygons.concat( this.front.allPolygons() );
850 if ( this.back ) polygons = polygons.concat( this.back.allPolygons() );
854 ThreeBSP.Node.prototype.numPolygons =
function() {
855 var res = this.polygons.length;
856 if ( this.front ) res += this.front.numPolygons();
857 if ( this.back ) res += this.back.numPolygons();
861 ThreeBSP.Node.prototype.clone =
function() {
862 var node =
new ThreeBSP.Node();
864 node.divider = this.divider.clone();
865 node.polygons = this.polygons.map(
function( polygon ) {
return polygon.clone(); } );
866 node.front = this.front && this.front.clone();
867 node.back = this.back && this.back.clone();
872 ThreeBSP.Node.prototype.invert =
function() {
873 var polygon_count = this.polygons.length;
875 for (var i = 0; i < polygon_count; ++i )
876 this.polygons[i].flip();
879 if ( this.front ) this.front.invert();
880 if ( this.back ) this.back.invert();
882 var temp = this.front;
883 this.front = this.back;
889 ThreeBSP.Node.prototype.clipPolygons =
function( polygons ) {
891 if ( !this.divider )
return polygons.slice();
893 var polygon_count = polygons.length, front = [], back = [];
895 for (var i = 0; i < polygon_count; ++i )
896 this.divider.splitPolygon( polygons[i], front, back, front, back );
898 if ( this.front ) front = this.front.clipPolygons( front );
899 if ( this.back ) back = this.back.clipPolygons( back );
902 return front.concat( back );
905 ThreeBSP.Node.prototype.clipTo =
function( node ) {
906 this.polygons = node.clipPolygons( this.polygons );
907 if ( this.front ) this.front.clipTo( node );
908 if ( this.back ) this.back.clipTo( node );