Pārlūkot izejas kodu

Examples: Removed THREE.Octree

Mugen87 6 gadi atpakaļ
vecāks
revīzija
7aa204e349

+ 0 - 1
docs/api/en/core/Raycaster.html

@@ -61,7 +61,6 @@
 			[example:webgl_interactive_lines Raycasting to a Line]<br />
 			[example:webgl_interactive_raycasting_points Raycasting to Points]<br />
 			[example:webgl_geometry_terrain_raycast Terrain raycasting]<br />
-			[example:webgl_octree_raycasting Raycasting using an octree]<br />
 			[example:webgl_interactive_voxelpainter Raycasting to paint voxels]<br />
 			[example:webgl_raycast_texture Raycast to a Texture]
 		</div>

+ 1 - 2
docs/api/zh/core/Raycaster.html

@@ -59,7 +59,6 @@
 			[example:webgl_interactive_lines Raycasting to a Line]<br />
 			[example:webgl_interactive_raycasting_points Raycasting to Points]<br />
 			[example:webgl_geometry_terrain_raycast Terrain raycasting]<br />
-			[example:webgl_octree_raycasting Raycasting using an octree]<br />
 			[example:webgl_interactive_voxelpainter Raycasting to paint voxels]<br />
 			[example:webgl_raycast_texture Raycast to a Texture]
 		</div>
@@ -136,7 +135,7 @@
 		<h3>[method:null setFromCamera]( [param:Vector2 coords], [param:Camera camera] )</h3>
 		<p>
 		[page:Vector2 coords] —— 在标准化设备坐标中鼠标的二维坐标 —— X分量与Y分量应当在-1到1之间。<br />
-								
+
 		[page:Camera camera] —— 射线所来源的摄像机。
 		</p>
 		<p>

+ 0 - 2
examples/files.js

@@ -198,8 +198,6 @@ var files = {
 		"webgl_multiple_scenes_comparison",
 		"webgl_multiple_views",
 		"webgl_nearestneighbour",
-		"webgl_octree",
-		"webgl_octree_raycasting",
 		"webgl_panorama_cube",
 		"webgl_panorama_dualfisheye",
 		"webgl_panorama_equirectangular",

+ 0 - 2143
examples/js/Octree.js

@@ -1,2143 +0,0 @@
-/*!
- *
- * threeoctree.js (r60) / https://github.com/collinhover/threeoctree
- * (sparse) dynamic 3D spatial representation structure for fast searches.
- *
- * @author Collin Hover / http://collinhover.com/
- * based on Dynamic Octree by Piko3D @ http://www.piko3d.com/ and Octree by Marek Pawlowski @ pawlowski.it
- *
- */
-( function ( THREE ) {
-
-	"use strict";
-
-	/*===================================================
-
-	utility
-
-	=====================================================*/
-
-	function isNumber( n ) {
-
-		return ! isNaN( n ) && isFinite( n );
-
-	}
-
-	function isArray( target ) {
-
-		return Object.prototype.toString.call( target ) === '[object Array]';
-
-	}
-
-	function toArray( target ) {
-
-		return target ? ( isArray( target ) !== true ? [ target ] : target ) : [];
-
-	}
-
-	function indexOfValue( array, value ) {
-
-		for ( var i = 0, il = array.length; i < il; i ++ ) {
-
-			if ( array[ i ] === value ) {
-
-				return i;
-
-			}
-
-		}
-
-		return - 1;
-
-	}
-
-	function indexOfPropertyWithValue( array, property, value ) {
-
-		for ( var i = 0, il = array.length; i < il; i ++ ) {
-
-			if ( array[ i ][ property ] === value ) {
-
-				return i;
-
-			}
-
-		}
-
-		return - 1;
-
-	}
-
-	/*===================================================
-
-	octree
-
-	=====================================================*/
-
-	THREE.Octree = function ( parameters ) {
-
-		// handle parameters
-
-		parameters = parameters || {};
-
-		parameters.tree = this;
-
-		// static properties ( modification is not recommended )
-
-		this.nodeCount = 0;
-
-		this.INDEX_INSIDE_CROSS = - 1;
-		this.INDEX_OUTSIDE_OFFSET = 2;
-
-		this.INDEX_OUTSIDE_POS_X = isNumber( parameters.INDEX_OUTSIDE_POS_X ) ? parameters.INDEX_OUTSIDE_POS_X : 0;
-		this.INDEX_OUTSIDE_NEG_X = isNumber( parameters.INDEX_OUTSIDE_NEG_X ) ? parameters.INDEX_OUTSIDE_NEG_X : 1;
-		this.INDEX_OUTSIDE_POS_Y = isNumber( parameters.INDEX_OUTSIDE_POS_Y ) ? parameters.INDEX_OUTSIDE_POS_Y : 2;
-		this.INDEX_OUTSIDE_NEG_Y = isNumber( parameters.INDEX_OUTSIDE_NEG_Y ) ? parameters.INDEX_OUTSIDE_NEG_Y : 3;
-		this.INDEX_OUTSIDE_POS_Z = isNumber( parameters.INDEX_OUTSIDE_POS_Z ) ? parameters.INDEX_OUTSIDE_POS_Z : 4;
-		this.INDEX_OUTSIDE_NEG_Z = isNumber( parameters.INDEX_OUTSIDE_NEG_Z ) ? parameters.INDEX_OUTSIDE_NEG_Z : 5;
-
-		this.INDEX_OUTSIDE_MAP = [];
-		this.INDEX_OUTSIDE_MAP[ this.INDEX_OUTSIDE_POS_X ] = { index: this.INDEX_OUTSIDE_POS_X, count: 0, x: 1, y: 0, z: 0 };
-		this.INDEX_OUTSIDE_MAP[ this.INDEX_OUTSIDE_NEG_X ] = { index: this.INDEX_OUTSIDE_NEG_X, count: 0, x: - 1, y: 0, z: 0 };
-		this.INDEX_OUTSIDE_MAP[ this.INDEX_OUTSIDE_POS_Y ] = { index: this.INDEX_OUTSIDE_POS_Y, count: 0, x: 0, y: 1, z: 0 };
-		this.INDEX_OUTSIDE_MAP[ this.INDEX_OUTSIDE_NEG_Y ] = { index: this.INDEX_OUTSIDE_NEG_Y, count: 0, x: 0, y: - 1, z: 0 };
-		this.INDEX_OUTSIDE_MAP[ this.INDEX_OUTSIDE_POS_Z ] = { index: this.INDEX_OUTSIDE_POS_Z, count: 0, x: 0, y: 0, z: 1 };
-		this.INDEX_OUTSIDE_MAP[ this.INDEX_OUTSIDE_NEG_Z ] = { index: this.INDEX_OUTSIDE_NEG_Z, count: 0, x: 0, y: 0, z: - 1 };
-
-		this.FLAG_POS_X = 1 << ( this.INDEX_OUTSIDE_POS_X + 1 );
-		this.FLAG_NEG_X = 1 << ( this.INDEX_OUTSIDE_NEG_X + 1 );
-		this.FLAG_POS_Y = 1 << ( this.INDEX_OUTSIDE_POS_Y + 1 );
-		this.FLAG_NEG_Y = 1 << ( this.INDEX_OUTSIDE_NEG_Y + 1 );
-		this.FLAG_POS_Z = 1 << ( this.INDEX_OUTSIDE_POS_Z + 1 );
-		this.FLAG_NEG_Z = 1 << ( this.INDEX_OUTSIDE_NEG_Z + 1 );
-
-		this.utilVec31Search = new THREE.Vector3();
-		this.utilVec32Search = new THREE.Vector3();
-
-		// pass scene to see octree structure
-
-		this.scene = parameters.scene;
-
-		if ( this.scene ) {
-
-			var helper = new THREE.BoxHelper( new THREE.Mesh( new THREE.BoxBufferGeometry( 1, 1, 1 ) ), 0xff0066 );
-			this.visualGeometry = helper.geometry;
-			this.visualMaterial = helper.material;
-
-		}
-
-		// properties
-
-		this.objects = [];
-		this.objectsMap = {};
-		this.objectsData = [];
-		this.objectsDeferred = [];
-
-		this.depthMax = isNumber( parameters.depthMax ) ? parameters.depthMax : Infinity;
-		this.objectsThreshold = isNumber( parameters.objectsThreshold ) ? parameters.objectsThreshold : 8;
-		this.overlapPct = isNumber( parameters.overlapPct ) ? parameters.overlapPct : 0.15;
-		this.undeferred = parameters.undeferred || false;
-
-		this.root = parameters.root instanceof THREE.OctreeNode ? parameters.root : new THREE.OctreeNode( parameters );
-
-	};
-
-	THREE.Octree.prototype = {
-
-		update: function () {
-
-			// add any deferred objects that were waiting for render cycle
-
-			if ( this.objectsDeferred.length > 0 ) {
-
-				for ( var i = 0, il = this.objectsDeferred.length; i < il; i ++ ) {
-
-					var deferred = this.objectsDeferred[ i ];
-
-					this.addDeferred( deferred.object, deferred.options );
-
-				}
-
-				this.objectsDeferred.length = 0;
-
-			}
-
-		},
-
-		add: function ( object, options ) {
-
-			// add immediately
-
-			if ( this.undeferred ) {
-
-				this.updateObject( object );
-
-				this.addDeferred( object, options );
-
-			} else {
-
-				// defer add until update called
-
-				this.objectsDeferred.push( { object: object, options: options } );
-
-			}
-
-		},
-
-		addDeferred: function ( object, options ) {
-
-			var i, l,
-				geometry,
-				faces,
-				useFaces,
-				vertices,
-				useVertices,
-				objectData;
-
-			// ensure object is not object data
-
-			if ( object instanceof THREE.OctreeObjectData ) {
-
-				object = object.object;
-
-			}
-
-			// check uuid to avoid duplicates
-
-			if ( ! object.uuid ) {
-
-				object.uuid = THREE.Math.generateUUID();
-
-			}
-
-			if ( ! this.objectsMap[ object.uuid ] ) {
-
-				// store
-
-				this.objects.push( object );
-				this.objectsMap[ object.uuid ] = object;
-
-				// check options
-
-				if ( options ) {
-
-					useFaces = options.useFaces;
-					useVertices = options.useVertices;
-
-				}
-
-				if ( useVertices === true ) {
-
-					geometry = object.geometry;
-					vertices = geometry.vertices;
-
-					for ( i = 0, l = vertices.length; i < l; i ++ ) {
-
-						this.addObjectData( object, vertices[ i ] );
-
-					}
-
-				} else if ( useFaces === true ) {
-
-					geometry = object.geometry;
-					faces = geometry.faces;
-
-					for ( i = 0, l = faces.length; i < l; i ++ ) {
-
-						this.addObjectData( object, faces[ i ] );
-
-					}
-
-				} else {
-
-					this.addObjectData( object );
-
-				}
-
-			}
-
-		},
-
-		addObjectData: function ( object, part ) {
-
-			var objectData = new THREE.OctreeObjectData( object, part );
-
-			// add to tree objects data list
-
-			this.objectsData.push( objectData );
-
-			// add to nodes
-
-			this.root.addObject( objectData );
-
-		},
-
-		remove: function ( object ) {
-
-			var i, l,
-				objectData = object,
-				index,
-				objectsDataRemoved;
-
-			// ensure object is not object data for index search
-
-			if ( object instanceof THREE.OctreeObjectData ) {
-
-				object = object.object;
-
-			}
-
-			// check uuid
-
-			if ( this.objectsMap[ object.uuid ] ) {
-
-				this.objectsMap[ object.uuid ] = undefined;
-
-				// check and remove from objects, nodes, and data lists
-
-				index = indexOfValue( this.objects, object );
-
-				if ( index !== - 1 ) {
-
-					this.objects.splice( index, 1 );
-
-					// remove from nodes
-
-					objectsDataRemoved = this.root.removeObject( objectData );
-
-					// remove from objects data list
-
-					for ( i = 0, l = objectsDataRemoved.length; i < l; i ++ ) {
-
-						objectData = objectsDataRemoved[ i ];
-
-						index = indexOfValue( this.objectsData, objectData );
-
-						if ( index !== - 1 ) {
-
-							this.objectsData.splice( index, 1 );
-
-						}
-
-					}
-
-				}
-
-			} else if ( this.objectsDeferred.length > 0 ) {
-
-				// check and remove from deferred
-
-				index = indexOfPropertyWithValue( this.objectsDeferred, 'object', object );
-
-				if ( index !== - 1 ) {
-
-					this.objectsDeferred.splice( index, 1 );
-
-				}
-
-			}
-
-		},
-
-		extend: function ( octree ) {
-
-			var i, l,
-				objectsData,
-				objectData;
-
-			if ( octree instanceof THREE.Octree ) {
-
-				// for each object data
-
-				objectsData = octree.objectsData;
-
-				for ( i = 0, l = objectsData.length; i < l; i ++ ) {
-
-					objectData = objectsData[ i ];
-
-					this.add( objectData, { useFaces: objectData.faces, useVertices: objectData.vertices } );
-
-				}
-
-			}
-
-		},
-
-		rebuild: function () {
-
-			var i, l,
-				node,
-				object,
-				objectData,
-				indexOctant,
-				indexOctantLast,
-				objectsUpdate = [];
-
-			// check all object data for changes in position
-			// assumes all object matrices are up to date
-
-			for ( i = 0, l = this.objectsData.length; i < l; i ++ ) {
-
-				objectData = this.objectsData[ i ];
-
-				node = objectData.node;
-
-				// update object
-
-				objectData.update();
-
-				// if position has changed since last organization of object in tree
-
-				if ( node instanceof THREE.OctreeNode && ! objectData.positionLast.equals( objectData.position ) ) {
-
-					// get octant index of object within current node
-
-					indexOctantLast = objectData.indexOctant;
-
-					indexOctant = node.getOctantIndex( objectData );
-
-					// if object octant index has changed
-
-					if ( indexOctant !== indexOctantLast ) {
-
-						// add to update list
-
-						objectsUpdate.push( objectData );
-
-					}
-
-				}
-
-			}
-
-			// update changed objects
-
-			for ( i = 0, l = objectsUpdate.length; i < l; i ++ ) {
-
-				objectData = objectsUpdate[ i ];
-
-				// remove object from current node
-
-				objectData.node.removeObject( objectData );
-
-				// add object to tree root
-
-				this.root.addObject( objectData );
-
-			}
-
-		},
-
-		updateObject: function ( object ) {
-
-			var i, l,
-				parentCascade = [ object ],
-				parent,
-				parentUpdate;
-
-			// search all parents between object and root for world matrix update
-
-			parent = object.parent;
-
-			while ( parent ) {
-
-				parentCascade.push( parent );
-				parent = parent.parent;
-
-			}
-
-			for ( i = 0, l = parentCascade.length; i < l; i ++ ) {
-
-				parent = parentCascade[ i ];
-
-				if ( parent.matrixWorldNeedsUpdate === true ) {
-
-					parentUpdate = parent;
-
-				}
-
-			}
-
-			// update world matrix starting at uppermost parent that needs update
-
-			if ( typeof parentUpdate !== 'undefined' ) {
-
-				parentUpdate.updateMatrixWorld();
-
-			}
-
-		},
-
-		search: function ( position, radius, organizeByObject, direction ) {
-
-			var i, l,
-				node,
-				objects,
-				objectData,
-				object,
-				results,
-				resultData,
-				resultsObjectsIndices,
-				resultObjectIndex,
-				directionPct;
-
-			// add root objects
-
-			objects = [].concat( this.root.objects );
-
-			// ensure radius (i.e. distance of ray) is a number
-
-			if ( ! ( radius > 0 ) ) {
-
-				radius = Number.MAX_VALUE;
-
-			}
-
-			// if direction passed, normalize and find pct
-
-			if ( direction instanceof THREE.Vector3 ) {
-
-				direction = this.utilVec31Search.copy( direction ).normalize();
-				directionPct = this.utilVec32Search.set( 1, 1, 1 ).divide( direction );
-
-			}
-
-			// search each node of root
-
-			for ( i = 0, l = this.root.nodesIndices.length; i < l; i ++ ) {
-
-				node = this.root.nodesByIndex[ this.root.nodesIndices[ i ] ];
-
-				objects = node.search( position, radius, objects, direction, directionPct );
-
-			}
-
-			// if should organize results by object
-
-			if ( organizeByObject === true ) {
-
-				results = [];
-				resultsObjectsIndices = [];
-
-				// for each object data found
-
-				for ( i = 0, l = objects.length; i < l; i ++ ) {
-
-					objectData = objects[ i ];
-					object = objectData.object;
-
-					resultObjectIndex = indexOfValue( resultsObjectsIndices, object );
-
-					// if needed, create new result data
-
-					if ( resultObjectIndex === - 1 ) {
-
-						resultData = {
-							object: object,
-							faces: [],
-							vertices: []
-						};
-
-						results.push( resultData );
-
-						resultsObjectsIndices.push( object );
-
-					} else {
-
-						resultData = results[ resultObjectIndex ];
-
-					}
-
-					// object data has faces or vertices, add to list
-
-					if ( objectData.faces ) {
-
-						resultData.faces.push( objectData.faces );
-
-					} else if ( objectData.vertices ) {
-
-						resultData.vertices.push( objectData.vertices );
-
-					}
-
-				}
-
-			} else {
-
-				results = objects;
-
-			}
-
-			return results;
-
-		},
-
-		setRoot: function ( root ) {
-
-			if ( root instanceof THREE.OctreeNode ) {
-
-				// store new root
-
-				this.root = root;
-
-				// update properties
-
-				this.root.updateProperties();
-
-			}
-
-		},
-
-		getDepthEnd: function () {
-
-			return this.root.getDepthEnd();
-
-		},
-
-		getNodeCountEnd: function () {
-
-			return this.root.getNodeCountEnd();
-
-		},
-
-		getObjectCountEnd: function () {
-
-			return this.root.getObjectCountEnd();
-
-		},
-
-		toConsole: function () {
-
-			this.root.toConsole();
-
-		}
-
-	};
-
-	/*===================================================
-
-	object data
-
-	=====================================================*/
-
-	THREE.OctreeObjectData = function ( object, part ) {
-
-		// properties
-
-		this.object = object;
-
-		// handle part by type
-
-		if ( part instanceof THREE.Face3 ) {
-
-			this.faces = part;
-			this.face3 = true;
-			this.utilVec31FaceBounds = new THREE.Vector3();
-
-		} else if ( part instanceof THREE.Vector3 ) {
-
-			this.vertices = part;
-
-		}
-
-		this.radius = 0;
-		this.position = new THREE.Vector3();
-
-		// initial update
-
-		if ( this.object instanceof THREE.Object3D ) {
-
-			this.update();
-
-		}
-
-		this.positionLast = this.position.clone();
-
-	};
-
-	THREE.OctreeObjectData.prototype = {
-
-		update: function () {
-
-			if ( this.face3 ) {
-
-				this.radius = this.getFace3BoundingRadius( this.object, this.faces );
-				this.position.copy( this.faces.centroid ).applyMatrix4( this.object.matrixWorld );
-
-			} else if ( this.vertices ) {
-
-				this.radius = this.object.material.size || 1;
-				this.position.copy( this.vertices ).applyMatrix4( this.object.matrixWorld );
-
-			} else {
-
-				if ( this.object.geometry ) {
-
-					if ( this.object.geometry.boundingSphere === null ) {
-
-						this.object.geometry.computeBoundingSphere();
-
-					}
-
-					this.radius = this.object.geometry.boundingSphere.radius;
-					this.position.copy( this.object.geometry.boundingSphere.center ).applyMatrix4( this.object.matrixWorld );
-
-				} else {
-
-					this.radius = this.object.boundRadius;
-					this.position.setFromMatrixPosition( this.object.matrixWorld );
-
-				}
-
-			}
-
-			this.radius = this.radius * Math.max( this.object.scale.x, this.object.scale.y, this.object.scale.z );
-
-		},
-
-		getFace3BoundingRadius: function ( object, face ) {
-
-			if ( face.centroid === undefined ) face.centroid = new THREE.Vector3();
-
-			var geometry = object.geometry || object,
-				vertices = geometry.vertices,
-				centroid = face.centroid,
-				va = vertices[ face.a ], vb = vertices[ face.b ], vc = vertices[ face.c ],
-				centroidToVert = this.utilVec31FaceBounds,
-				radius;
-
-			centroid.addVectors( va, vb ).add( vc ).divideScalar( 3 );
-			radius = Math.max( centroidToVert.subVectors( centroid, va ).length(), centroidToVert.subVectors( centroid, vb ).length(), centroidToVert.subVectors( centroid, vc ).length() );
-
-			return radius;
-
-		}
-
-	};
-
-	/*===================================================
-
-	node
-
-	=====================================================*/
-
-	THREE.OctreeNode = function ( parameters ) {
-
-		// utility
-
-		this.utilVec31Branch = new THREE.Vector3();
-		this.utilVec31Expand = new THREE.Vector3();
-		this.utilVec31Ray = new THREE.Vector3();
-
-		// handle parameters
-
-		parameters = parameters || {};
-
-		// store or create tree
-
-		if ( parameters.tree instanceof THREE.Octree ) {
-
-			this.tree = parameters.tree;
-
-		} else if ( parameters.parent instanceof THREE.OctreeNode !== true ) {
-
-			parameters.root = this;
-
-			this.tree = new THREE.Octree( parameters );
-
-		}
-
-		// basic properties
-
-		this.id = this.tree.nodeCount ++;
-		this.position = parameters.position instanceof THREE.Vector3 ? parameters.position : new THREE.Vector3();
-		this.radius = parameters.radius > 0 ? parameters.radius : 1;
-		this.indexOctant = parameters.indexOctant;
-		this.depth = 0;
-
-		// reset and assign parent
-
-		this.reset();
-		this.setParent( parameters.parent );
-
-		// additional properties
-
-		this.overlap = this.radius * this.tree.overlapPct;
-		this.radiusOverlap = this.radius + this.overlap;
-		this.left = this.position.x - this.radiusOverlap;
-		this.right = this.position.x + this.radiusOverlap;
-		this.bottom = this.position.y - this.radiusOverlap;
-		this.top = this.position.y + this.radiusOverlap;
-		this.back = this.position.z - this.radiusOverlap;
-		this.front = this.position.z + this.radiusOverlap;
-
-		// visual
-
-		if ( this.tree.scene ) {
-
-			this.visual = new THREE.LineSegments( this.tree.visualGeometry, this.tree.visualMaterial );
-			this.visual.scale.set( this.radiusOverlap * 2, this.radiusOverlap * 2, this.radiusOverlap * 2 );
-			this.visual.position.copy( this.position );
-			this.tree.scene.add( this.visual );
-
-		}
-
-	};
-
-	THREE.OctreeNode.prototype = {
-
-		setParent: function ( parent ) {
-
-			// store new parent
-
-			if ( parent !== this && this.parent !== parent ) {
-
-				this.parent = parent;
-
-				// update properties
-
-				this.updateProperties();
-
-			}
-
-		},
-
-		updateProperties: function () {
-
-			var i, l;
-
-			// properties
-
-			if ( this.parent instanceof THREE.OctreeNode ) {
-
-				this.tree = this.parent.tree;
-				this.depth = this.parent.depth + 1;
-
-			} else {
-
-				this.depth = 0;
-
-			}
-
-			// cascade
-
-			for ( i = 0, l = this.nodesIndices.length; i < l; i ++ ) {
-
-				this.nodesByIndex[ this.nodesIndices[ i ] ].updateProperties();
-
-			}
-
-		},
-
-		reset: function ( cascade, removeVisual ) {
-
-			var i, l,
-				node,
-				nodesIndices = this.nodesIndices || [],
-				nodesByIndex = this.nodesByIndex;
-
-			this.objects = [];
-			this.nodesIndices = [];
-			this.nodesByIndex = {};
-
-			// unset parent in nodes
-
-			for ( i = 0, l = nodesIndices.length; i < l; i ++ ) {
-
-				node = nodesByIndex[ nodesIndices[ i ] ];
-
-				node.setParent( undefined );
-
-				if ( cascade === true ) {
-
-					node.reset( cascade, removeVisual );
-
-				}
-
-			}
-
-			// visual
-
-			if ( removeVisual === true && this.visual && this.visual.parent ) {
-
-				this.visual.parent.remove( this.visual );
-
-			}
-
-		},
-
-		addNode: function ( node, indexOctant ) {
-
-			node.indexOctant = indexOctant;
-
-			if ( indexOfValue( this.nodesIndices, indexOctant ) === - 1 ) {
-
-				this.nodesIndices.push( indexOctant );
-
-			}
-
-			this.nodesByIndex[ indexOctant ] = node;
-
-			if ( node.parent !== this ) {
-
-				node.setParent( this );
-
-			}
-
-		},
-
-		removeNode: function ( indexOctant ) {
-
-			var index,
-				node;
-
-			index = indexOfValue( this.nodesIndices, indexOctant );
-
-			this.nodesIndices.splice( index, 1 );
-
-			node = node || this.nodesByIndex[ indexOctant ];
-
-			delete this.nodesByIndex[ indexOctant ];
-
-			if ( node.parent === this ) {
-
-				node.setParent( undefined );
-
-			}
-
-		},
-
-		addObject: function ( object ) {
-
-			var index,
-				indexOctant,
-				node;
-
-			// get object octant index
-
-			indexOctant = this.getOctantIndex( object );
-
-			// if object fully contained by an octant, add to subtree
-			if ( indexOctant > - 1 && this.nodesIndices.length > 0 ) {
-
-				node = this.branch( indexOctant );
-
-				node.addObject( object );
-
-			} else if ( indexOctant < - 1 && this.parent instanceof THREE.OctreeNode ) {
-
-				// if object lies outside bounds, add to parent node
-
-				this.parent.addObject( object );
-
-			} else {
-
-				// add to this objects list
-
-				index = indexOfValue( this.objects, object );
-
-				if ( index === - 1 ) {
-
-					this.objects.push( object );
-
-				}
-
-				// node reference
-
-				object.node = this;
-
-				// check if need to expand, split, or both
-
-				this.checkGrow();
-
-			}
-
-		},
-
-		addObjectWithoutCheck: function ( objects ) {
-
-			var i, l,
-				object;
-
-			for ( i = 0, l = objects.length; i < l; i ++ ) {
-
-				object = objects[ i ];
-
-				this.objects.push( object );
-
-				object.node = this;
-
-			}
-
-		},
-
-		removeObject: function ( object ) {
-
-			var i, l,
-				nodesRemovedFrom,
-				removeData;
-
-			// cascade through tree to find and remove object
-
-			removeData = this.removeObjectRecursive( object, { searchComplete: false, nodesRemovedFrom: [], objectsDataRemoved: [] } );
-
-			// if object removed, try to shrink the nodes it was removed from
-
-			nodesRemovedFrom = removeData.nodesRemovedFrom;
-
-			if ( nodesRemovedFrom.length > 0 ) {
-
-				for ( i = 0, l = nodesRemovedFrom.length; i < l; i ++ ) {
-
-					nodesRemovedFrom[ i ].shrink();
-
-				}
-
-			}
-
-			return removeData.objectsDataRemoved;
-
-		},
-
-		removeObjectRecursive: function ( object, removeData ) {
-
-			var i, l,
-				index = - 1,
-				objectData,
-				node,
-				objectRemoved;
-
-			// find index of object in objects list
-
-			// search and remove object data (fast)
-			if ( object instanceof THREE.OctreeObjectData ) {
-
-				// remove from this objects list
-
-				index = indexOfValue( this.objects, object );
-
-				if ( index !== - 1 ) {
-
-					this.objects.splice( index, 1 );
-					object.node = undefined;
-
-					removeData.objectsDataRemoved.push( object );
-
-					removeData.searchComplete = objectRemoved = true;
-
-				}
-
-			} else {
-
-				// search each object data for object and remove (slow)
-
-				for ( i = this.objects.length - 1; i >= 0; i -- ) {
-
-					objectData = this.objects[ i ];
-
-					if ( objectData.object === object ) {
-
-						this.objects.splice( i, 1 );
-						objectData.node = undefined;
-
-						removeData.objectsDataRemoved.push( objectData );
-
-						objectRemoved = true;
-
-						if ( ! objectData.faces && ! objectData.vertices ) {
-
-							removeData.searchComplete = true;
-							break;
-
-						}
-
-					}
-
-				}
-
-			}
-
-			// if object data removed and this is not on nodes removed from
-
-			if ( objectRemoved === true ) {
-
-				removeData.nodesRemovedFrom.push( this );
-
-			}
-
-			// if search not complete, search nodes
-
-			if ( removeData.searchComplete !== true ) {
-
-				for ( i = 0, l = this.nodesIndices.length; i < l; i ++ ) {
-
-					node = this.nodesByIndex[ this.nodesIndices[ i ] ];
-
-					// try removing object from node
-
-					removeData = node.removeObjectRecursive( object, removeData );
-
-					if ( removeData.searchComplete === true ) {
-
-						break;
-
-					}
-
-				}
-
-			}
-
-			return removeData;
-
-		},
-
-		checkGrow: function () {
-
-			// if object count above max
-
-			if ( this.objects.length > this.tree.objectsThreshold && this.tree.objectsThreshold > 0 ) {
-
-				this.grow();
-
-			}
-
-		},
-
-		grow: function () {
-
-			var indexOctant,
-				object,
-				objectsExpand = [],
-				objectsExpandOctants = [],
-				objectsSplit = [],
-				objectsSplitOctants = [],
-				objectsRemaining = [],
-				i, l;
-
-			// for each object
-
-			for ( i = 0, l = this.objects.length; i < l; i ++ ) {
-
-				object = this.objects[ i ];
-
-				// get object octant index
-
-				indexOctant = this.getOctantIndex( object );
-
-				// if lies within octant
-				if ( indexOctant > - 1 ) {
-
-					objectsSplit.push( object );
-					objectsSplitOctants.push( indexOctant );
-
-				} else if ( indexOctant < - 1 ) {
-
-					// lies outside radius
-
-					objectsExpand.push( object );
-					objectsExpandOctants.push( indexOctant );
-
-				} else {
-
-					// lies across bounds between octants
-
-					objectsRemaining.push( object );
-
-				}
-
-			}
-
-			// if has objects to split
-
-			if ( objectsSplit.length > 0 ) {
-
-				objectsRemaining = objectsRemaining.concat( this.split( objectsSplit, objectsSplitOctants ) );
-
-			}
-
-			// if has objects to expand
-
-			if ( objectsExpand.length > 0 ) {
-
-				objectsRemaining = objectsRemaining.concat( this.expand( objectsExpand, objectsExpandOctants ) );
-
-			}
-
-			// store remaining
-
-			this.objects = objectsRemaining;
-
-			// merge check
-
-			this.checkMerge();
-
-		},
-
-		split: function ( objects, octants ) {
-
-			var i, l,
-				indexOctant,
-				object,
-				node,
-				objectsRemaining;
-
-			// if not at max depth
-
-			if ( this.depth < this.tree.depthMax ) {
-
-				objects = objects || this.objects;
-
-				octants = octants || [];
-
-				objectsRemaining = [];
-
-				// for each object
-
-				for ( i = 0, l = objects.length; i < l; i ++ ) {
-
-					object = objects[ i ];
-
-					// get object octant index
-
-					indexOctant = octants[ i ];
-
-					// if object contained by octant, branch this tree
-
-					if ( indexOctant > - 1 ) {
-
-						node = this.branch( indexOctant );
-
-						node.addObject( object );
-
-					} else {
-
-						objectsRemaining.push( object );
-
-					}
-
-				}
-
-				// if all objects, set remaining as new objects
-
-				if ( objects === this.objects ) {
-
-					this.objects = objectsRemaining;
-
-				}
-
-			} else {
-
-				objectsRemaining = this.objects;
-
-			}
-
-			return objectsRemaining;
-
-		},
-
-		branch: function ( indexOctant ) {
-
-			var node,
-				overlap,
-				radius,
-				radiusOffset,
-				offset,
-				position;
-
-			// node exists
-
-			if ( this.nodesByIndex[ indexOctant ] instanceof THREE.OctreeNode ) {
-
-				node = this.nodesByIndex[ indexOctant ];
-
-			} else {
-
-				// properties
-
-				radius = ( this.radiusOverlap ) * 0.5;
-				overlap = radius * this.tree.overlapPct;
-				radiusOffset = radius - overlap;
-				offset = this.utilVec31Branch.set( indexOctant & 1 ? radiusOffset : - radiusOffset, indexOctant & 2 ? radiusOffset : - radiusOffset, indexOctant & 4 ? radiusOffset : - radiusOffset );
-				position = new THREE.Vector3().addVectors( this.position, offset );
-
-				// node
-
-				node = new THREE.OctreeNode( {
-					tree: this.tree,
-					parent: this,
-					position: position,
-					radius: radius,
-					indexOctant: indexOctant
-				} );
-
-				// store
-
-				this.addNode( node, indexOctant );
-
-			}
-
-			return node;
-
-		},
-
-		expand: function ( objects, octants ) {
-
-			var i, l,
-				object,
-				objectsRemaining,
-				objectsExpand,
-				indexOctant,
-				flagsOutside,
-				indexOutside,
-				indexOctantInverse,
-				iom = this.tree.INDEX_OUTSIDE_MAP,
-				indexOutsideCounts,
-				infoIndexOutside1,
-				infoIndexOutside2,
-				infoIndexOutside3,
-				indexOutsideBitwise1,
-				indexOutsideBitwise2,
-				infoPotential1,
-				infoPotential2,
-				infoPotential3,
-				indexPotentialBitwise1,
-				indexPotentialBitwise2,
-				octantX, octantY, octantZ,
-				overlap,
-				radius,
-				radiusOffset,
-				radiusParent,
-				overlapParent,
-				offset = this.utilVec31Expand,
-				position,
-				parent;
-
-			// handle max depth down tree
-
-			if ( this.tree.root.getDepthEnd() < this.tree.depthMax ) {
-
-				objects = objects || this.objects;
-				octants = octants || [];
-
-				objectsRemaining = [];
-				objectsExpand = [];
-
-				// reset counts
-
-				for ( i = 0, l = iom.length; i < l; i ++ ) {
-
-					iom[ i ].count = 0;
-
-				}
-
-				// for all outside objects, find outside octants containing most objects
-
-				for ( i = 0, l = objects.length; i < l; i ++ ) {
-
-					object = objects[ i ];
-
-					// get object octant index
-
-					indexOctant = octants[ i ];
-
-					// if object outside this, include in calculations
-
-					if ( indexOctant < - 1 ) {
-
-						// convert octant index to outside flags
-
-						flagsOutside = - indexOctant - this.tree.INDEX_OUTSIDE_OFFSET;
-
-						// check against bitwise flags
-
-						// x
-
-						if ( flagsOutside & this.tree.FLAG_POS_X ) {
-
-							iom[ this.tree.INDEX_OUTSIDE_POS_X ].count ++;
-
-						} else if ( flagsOutside & this.tree.FLAG_NEG_X ) {
-
-							iom[ this.tree.INDEX_OUTSIDE_NEG_X ].count ++;
-
-						}
-
-						// y
-
-						if ( flagsOutside & this.tree.FLAG_POS_Y ) {
-
-							iom[ this.tree.INDEX_OUTSIDE_POS_Y ].count ++;
-
-						} else if ( flagsOutside & this.tree.FLAG_NEG_Y ) {
-
-							iom[ this.tree.INDEX_OUTSIDE_NEG_Y ].count ++;
-
-						}
-
-						// z
-
-						if ( flagsOutside & this.tree.FLAG_POS_Z ) {
-
-							iom[ this.tree.INDEX_OUTSIDE_POS_Z ].count ++;
-
-						} else if ( flagsOutside & this.tree.FLAG_NEG_Z ) {
-
-							iom[ this.tree.INDEX_OUTSIDE_NEG_Z ].count ++;
-
-						}
-
-						// store in expand list
-
-						objectsExpand.push( object );
-
-					} else {
-
-						objectsRemaining.push( object );
-
-					}
-
-				}
-
-				// if objects to expand
-
-				if ( objectsExpand.length > 0 ) {
-
-					// shallow copy index outside map
-
-					indexOutsideCounts = iom.slice( 0 );
-
-					// sort outside index count so highest is first
-
-					indexOutsideCounts.sort( function ( a, b ) {
-
-						return b.count - a.count;
-
-					} );
-
-					// get highest outside indices
-
-					// first is first
-					infoIndexOutside1 = indexOutsideCounts[ 0 ];
-					indexOutsideBitwise1 = infoIndexOutside1.index | 1;
-
-					// second is ( one of next two bitwise OR 1 ) that is not opposite of ( first bitwise OR 1 )
-
-					infoPotential1 = indexOutsideCounts[ 1 ];
-					infoPotential2 = indexOutsideCounts[ 2 ];
-
-					infoIndexOutside2 = ( infoPotential1.index | 1 ) !== indexOutsideBitwise1 ? infoPotential1 : infoPotential2;
-					indexOutsideBitwise2 = infoIndexOutside2.index | 1;
-
-					// third is ( one of next three bitwise OR 1 ) that is not opposite of ( first or second bitwise OR 1 )
-
-					infoPotential1 = indexOutsideCounts[ 2 ];
-					infoPotential2 = indexOutsideCounts[ 3 ];
-					infoPotential3 = indexOutsideCounts[ 4 ];
-
-					indexPotentialBitwise1 = infoPotential1.index | 1;
-					indexPotentialBitwise2 = infoPotential2.index | 1;
-
-					infoIndexOutside3 = indexPotentialBitwise1 !== indexOutsideBitwise1 && indexPotentialBitwise1 !== indexOutsideBitwise2 ? infoPotential1 : indexPotentialBitwise2 !== indexOutsideBitwise1 && indexPotentialBitwise2 !== indexOutsideBitwise2 ? infoPotential2 : infoPotential3;
-
-					// get this octant normal based on outside octant indices
-
-					octantX = infoIndexOutside1.x + infoIndexOutside2.x + infoIndexOutside3.x;
-					octantY = infoIndexOutside1.y + infoIndexOutside2.y + infoIndexOutside3.y;
-					octantZ = infoIndexOutside1.z + infoIndexOutside2.z + infoIndexOutside3.z;
-
-					// get this octant indices based on octant normal
-
-					indexOctant = this.getOctantIndexFromPosition( octantX, octantY, octantZ );
-					indexOctantInverse = this.getOctantIndexFromPosition( - octantX, - octantY, - octantZ );
-
-					// properties
-
-					overlap = this.overlap;
-					radius = this.radius;
-
-					// radius of parent comes from reversing overlap of this, unless overlap percent is 0
-
-					radiusParent = this.tree.overlapPct > 0 ? overlap / ( ( 0.5 * this.tree.overlapPct ) * ( 1 + this.tree.overlapPct ) ) : radius * 2;
-					overlapParent = radiusParent * this.tree.overlapPct;
-
-					// parent offset is difference between radius + overlap of parent and child
-
-					radiusOffset = ( radiusParent + overlapParent ) - ( radius + overlap );
-					offset.set( indexOctant & 1 ? radiusOffset : - radiusOffset, indexOctant & 2 ? radiusOffset : - radiusOffset, indexOctant & 4 ? radiusOffset : - radiusOffset );
-					position = new THREE.Vector3().addVectors( this.position, offset );
-
-					// parent
-
-					parent = new THREE.OctreeNode( {
-						tree: this.tree,
-						position: position,
-						radius: radiusParent
-					} );
-
-					// set self as node of parent
-
-					parent.addNode( this, indexOctantInverse );
-
-					// set parent as root
-
-					this.tree.setRoot( parent );
-
-					// add all expand objects to parent
-
-					for ( i = 0, l = objectsExpand.length; i < l; i ++ ) {
-
-						this.tree.root.addObject( objectsExpand[ i ] );
-
-					}
-
-				}
-
-				// if all objects, set remaining as new objects
-
-				if ( objects === this.objects ) {
-
-					this.objects = objectsRemaining;
-
-				}
-
-			} else {
-
-				objectsRemaining = objects;
-
-			}
-
-			return objectsRemaining;
-
-		},
-
-		shrink: function () {
-
-			// merge check
-
-			this.checkMerge();
-
-			// contract check
-
-			this.tree.root.checkContract();
-
-		},
-
-		checkMerge: function () {
-
-			var nodeParent = this,
-				nodeMerge;
-
-			// traverse up tree as long as node + entire subtree's object count is under minimum
-
-			while ( nodeParent.parent instanceof THREE.OctreeNode && nodeParent.getObjectCountEnd() < this.tree.objectsThreshold ) {
-
-				nodeMerge = nodeParent;
-				nodeParent = nodeParent.parent;
-
-			}
-
-			// if parent node is not this, merge entire subtree into merge node
-
-			if ( nodeParent !== this ) {
-
-				nodeParent.merge( nodeMerge );
-
-			}
-
-		},
-
-		merge: function ( nodes ) {
-
-			var i, l,
-				j, k,
-				node;
-
-			// handle nodes
-
-			nodes = toArray( nodes );
-
-			for ( i = 0, l = nodes.length; i < l; i ++ ) {
-
-				node = nodes[ i ];
-
-				// gather node + all subtree objects
-
-				this.addObjectWithoutCheck( node.getObjectsEnd() );
-
-				// reset node + entire subtree
-
-				node.reset( true, true );
-
-				// remove node
-
-				this.removeNode( node.indexOctant, node );
-
-			}
-
-			// merge check
-
-			this.checkMerge();
-
-		},
-
-		checkContract: function () {
-
-			var i, l,
-				node,
-				nodeObjectsCount,
-				nodeHeaviest,
-				nodeHeaviestObjectsCount,
-				outsideHeaviestObjectsCount;
-
-			// find node with highest object count
-
-			if ( this.nodesIndices.length > 0 ) {
-
-				nodeHeaviestObjectsCount = 0;
-				outsideHeaviestObjectsCount = this.objects.length;
-
-				for ( i = 0, l = this.nodesIndices.length; i < l; i ++ ) {
-
-					node = this.nodesByIndex[ this.nodesIndices[ i ] ];
-
-					nodeObjectsCount = node.getObjectCountEnd();
-					outsideHeaviestObjectsCount += nodeObjectsCount;
-
-					if ( nodeHeaviest instanceof THREE.OctreeNode === false || nodeObjectsCount > nodeHeaviestObjectsCount ) {
-
-						nodeHeaviest = node;
-						nodeHeaviestObjectsCount = nodeObjectsCount;
-
-					}
-
-				}
-
-				// subtract heaviest count from outside count
-
-				outsideHeaviestObjectsCount -= nodeHeaviestObjectsCount;
-
-				// if should contract
-
-				if ( outsideHeaviestObjectsCount < this.tree.objectsThreshold && nodeHeaviest instanceof THREE.OctreeNode ) {
-
-					this.contract( nodeHeaviest );
-
-				}
-
-			}
-
-		},
-
-		contract: function ( nodeRoot ) {
-
-			var i, l,
-				node;
-
-			// handle all nodes
-
-			for ( i = 0, l = this.nodesIndices.length; i < l; i ++ ) {
-
-				node = this.nodesByIndex[ this.nodesIndices[ i ] ];
-
-				// if node is not new root
-
-				if ( node !== nodeRoot ) {
-
-					// add node + all subtree objects to root
-
-					nodeRoot.addObjectWithoutCheck( node.getObjectsEnd() );
-
-					// reset node + entire subtree
-
-					node.reset( true, true );
-
-				}
-
-			}
-
-			// add own objects to root
-
-			nodeRoot.addObjectWithoutCheck( this.objects );
-
-			// reset self
-
-			this.reset( false, true );
-
-			// set new root
-
-			this.tree.setRoot( nodeRoot );
-
-			// contract check on new root
-
-			nodeRoot.checkContract();
-
-		},
-
-		getOctantIndex: function ( objectData ) {
-
-			var i, l,
-				positionObj,
-				radiusObj,
-				position = this.position,
-				radiusOverlap = this.radiusOverlap,
-				overlap = this.overlap,
-				deltaX, deltaY, deltaZ,
-				distX, distY, distZ,
-				distance,
-				indexOctant = 0;
-
-			// handle type
-
-			if ( objectData instanceof THREE.OctreeObjectData ) {
-
-				radiusObj = objectData.radius;
-
-				positionObj = objectData.position;
-
-				// update object data position last
-
-				objectData.positionLast.copy( positionObj );
-
-			} else if ( objectData instanceof THREE.OctreeNode ) {
-
-				positionObj = objectData.position;
-
-				radiusObj = 0;
-
-			}
-
-			// find delta and distance
-
-			deltaX = positionObj.x - position.x;
-			deltaY = positionObj.y - position.y;
-			deltaZ = positionObj.z - position.z;
-
-			distX = Math.abs( deltaX );
-			distY = Math.abs( deltaY );
-			distZ = Math.abs( deltaZ );
-			distance = Math.max( distX, distY, distZ );
-
-			// if outside, use bitwise flags to indicate on which sides object is outside of
-
-			if ( distance + radiusObj > radiusOverlap ) {
-
-				// x
-
-				if ( distX + radiusObj > radiusOverlap ) {
-
-					indexOctant = indexOctant ^ ( deltaX > 0 ? this.tree.FLAG_POS_X : this.tree.FLAG_NEG_X );
-
-				}
-
-				// y
-
-				if ( distY + radiusObj > radiusOverlap ) {
-
-					indexOctant = indexOctant ^ ( deltaY > 0 ? this.tree.FLAG_POS_Y : this.tree.FLAG_NEG_Y );
-
-				}
-
-				// z
-
-				if ( distZ + radiusObj > radiusOverlap ) {
-
-					indexOctant = indexOctant ^ ( deltaZ > 0 ? this.tree.FLAG_POS_Z : this.tree.FLAG_NEG_Z );
-
-				}
-
-				objectData.indexOctant = - indexOctant - this.tree.INDEX_OUTSIDE_OFFSET;
-
-				return objectData.indexOctant;
-
-			}
-
-			// return octant index from delta xyz
-
-			if ( deltaX - radiusObj > - overlap ) {
-
-				// x right
-
-				indexOctant = indexOctant | 1;
-
-			} else if ( ! ( deltaX + radiusObj < overlap ) ) {
-
-				// x left
-
-				objectData.indexOctant = this.tree.INDEX_INSIDE_CROSS;
-				return objectData.indexOctant;
-
-			}
-
-			if ( deltaY - radiusObj > - overlap ) {
-
-				// y right
-
-				indexOctant = indexOctant | 2;
-
-			} else if ( ! ( deltaY + radiusObj < overlap ) ) {
-
-				// y left
-
-				objectData.indexOctant = this.tree.INDEX_INSIDE_CROSS;
-				return objectData.indexOctant;
-
-			}
-
-
-			if ( deltaZ - radiusObj > - overlap ) {
-
-				// z right
-
-				indexOctant = indexOctant | 4;
-
-			} else if ( ! ( deltaZ + radiusObj < overlap ) ) {
-
-				// z left
-
-				objectData.indexOctant = this.tree.INDEX_INSIDE_CROSS;
-				return objectData.indexOctant;
-
-			}
-
-			objectData.indexOctant = indexOctant;
-			return objectData.indexOctant;
-
-		},
-
-		getOctantIndexFromPosition: function ( x, y, z ) {
-
-			var indexOctant = 0;
-
-			if ( x > 0 ) {
-
-				indexOctant = indexOctant | 1;
-
-			}
-
-			if ( y > 0 ) {
-
-				indexOctant = indexOctant | 2;
-
-			}
-
-			if ( z > 0 ) {
-
-				indexOctant = indexOctant | 4;
-
-			}
-
-			return indexOctant;
-
-		},
-
-		search: function ( position, radius, objects, direction, directionPct ) {
-
-			var i, l,
-				node,
-				intersects;
-
-			// test intersects by parameters
-
-			if ( direction ) {
-
-				intersects = this.intersectRay( position, direction, radius, directionPct );
-
-			} else {
-
-				intersects = this.intersectSphere( position, radius );
-
-			}
-
-			// if intersects
-
-			if ( intersects === true ) {
-
-				// gather objects
-
-				objects = objects.concat( this.objects );
-
-				// search subtree
-
-				for ( i = 0, l = this.nodesIndices.length; i < l; i ++ ) {
-
-					node = this.nodesByIndex[ this.nodesIndices[ i ] ];
-
-					objects = node.search( position, radius, objects, direction );
-
-				}
-
-			}
-
-			return objects;
-
-		},
-
-		intersectSphere: function ( position, radius ) {
-
-			var	distance = radius * radius,
-				px = position.x,
-				py = position.y,
-				pz = position.z;
-
-			if ( px < this.left ) {
-
-				distance -= Math.pow( px - this.left, 2 );
-
-			} else if ( px > this.right ) {
-
-				distance -= Math.pow( px - this.right, 2 );
-
-			}
-
-			if ( py < this.bottom ) {
-
-				distance -= Math.pow( py - this.bottom, 2 );
-
-			} else if ( py > this.top ) {
-
-				distance -= Math.pow( py - this.top, 2 );
-
-			}
-
-			if ( pz < this.back ) {
-
-				distance -= Math.pow( pz - this.back, 2 );
-
-			} else if ( pz > this.front ) {
-
-				distance -= Math.pow( pz - this.front, 2 );
-
-			}
-
-			return distance >= 0;
-
-		},
-
-		intersectRay: function ( origin, direction, distance, directionPct ) {
-
-			if ( typeof directionPct === 'undefined' ) {
-
-				directionPct = this.utilVec31Ray.set( 1, 1, 1 ).divide( direction );
-
-			}
-
-			var t1 = ( this.left - origin.x ) * directionPct.x,
-				t2 = ( this.right - origin.x ) * directionPct.x,
-				t3 = ( this.bottom - origin.y ) * directionPct.y,
-				t4 = ( this.top - origin.y ) * directionPct.y,
-				t5 = ( this.back - origin.z ) * directionPct.z,
-				t6 = ( this.front - origin.z ) * directionPct.z,
-				tmax = Math.min( Math.min( Math.max( t1, t2 ), Math.max( t3, t4 ) ), Math.max( t5, t6 ) ),
-				tmin;
-
-			// ray would intersect in reverse direction, i.e. this is behind ray
-			if ( tmax < 0 ) {
-
-				return false;
-
-			}
-
-			tmin = Math.max( Math.max( Math.min( t1, t2 ), Math.min( t3, t4 ) ), Math.min( t5, t6 ) );
-
-			// if tmin > tmax or tmin > ray distance, ray doesn't intersect AABB
-			if ( tmin > tmax || tmin > distance ) {
-
-				return false;
-
-			}
-
-			return true;
-
-		},
-
-		getDepthEnd: function ( depth ) {
-
-			var i, l,
-				node;
-
-			if ( this.nodesIndices.length > 0 ) {
-
-				for ( i = 0, l = this.nodesIndices.length; i < l; i ++ ) {
-
-					node = this.nodesByIndex[ this.nodesIndices[ i ] ];
-
-					depth = node.getDepthEnd( depth );
-
-				}
-
-			} else {
-
-				depth = ! depth || this.depth > depth ? this.depth : depth;
-
-			}
-
-			return depth;
-
-		},
-
-		getNodeCountEnd: function () {
-
-			return this.tree.root.getNodeCountRecursive() + 1;
-
-		},
-
-		getNodeCountRecursive: function () {
-
-			var i, l,
-				count = this.nodesIndices.length;
-
-			for ( i = 0, l = this.nodesIndices.length; i < l; i ++ ) {
-
-				count += this.nodesByIndex[ this.nodesIndices[ i ] ].getNodeCountRecursive();
-
-			}
-
-			return count;
-
-		},
-
-		getObjectsEnd: function ( objects ) {
-
-			var i, l,
-				node;
-
-			objects = ( objects || [] ).concat( this.objects );
-
-			for ( i = 0, l = this.nodesIndices.length; i < l; i ++ ) {
-
-				node = this.nodesByIndex[ this.nodesIndices[ i ] ];
-
-				objects = node.getObjectsEnd( objects );
-
-			}
-
-			return objects;
-
-		},
-
-		getObjectCountEnd: function () {
-
-			var i, l,
-				count = this.objects.length;
-
-			for ( i = 0, l = this.nodesIndices.length; i < l; i ++ ) {
-
-				count += this.nodesByIndex[ this.nodesIndices[ i ] ].getObjectCountEnd();
-
-			}
-
-			return count;
-
-		},
-
-		getObjectCountStart: function () {
-
-			var count = this.objects.length,
-				parent = this.parent;
-
-			while ( parent instanceof THREE.OctreeNode ) {
-
-				count += parent.objects.length;
-				parent = parent.parent;
-
-			}
-
-			return count;
-
-		},
-
-		toConsole: function ( space ) {
-
-			var i, l,
-				node,
-				spaceAddition = '   ';
-
-			space = typeof space === 'string' ? space : spaceAddition;
-
-			console.log( ( this.parent ? space + ' octree NODE > ' : ' octree ROOT > ' ), this, ' // id: ', this.id, ' // indexOctant: ', this.indexOctant, ' // position: ', this.position.x, this.position.y, this.position.z, ' // radius: ', this.radius, ' // depth: ', this.depth );
-			console.log( ( this.parent ? space + ' ' : ' ' ), '+ objects ( ', this.objects.length, ' ) ', this.objects );
-			console.log( ( this.parent ? space + ' ' : ' ' ), '+ children ( ', this.nodesIndices.length, ' )', this.nodesIndices, this.nodesByIndex );
-
-			for ( i = 0, l = this.nodesIndices.length; i < l; i ++ ) {
-
-				node = this.nodesByIndex[ this.nodesIndices[ i ] ];
-
-				node.toConsole( space + spaceAddition );
-
-			}
-
-		}
-
-	};
-
-	/*===================================================
-
-	raycaster additional functionality
-
-	=====================================================*/
-
-	THREE.Raycaster.prototype.intersectOctreeObject = function ( object, recursive ) {
-
-		var intersects,
-			octreeObject,
-			facesAll,
-			facesSearch;
-
-		if ( object.object instanceof THREE.Object3D ) {
-
-			octreeObject = object;
-			object = octreeObject.object;
-
-			// temporarily replace object geometry's faces with octree object faces
-
-			facesSearch = octreeObject.faces;
-			facesAll = object.geometry.faces;
-
-			if ( facesSearch.length > 0 ) {
-
-				object.geometry.faces = facesSearch;
-
-			}
-
-			// intersect
-
-			intersects = this.intersectObject( object, recursive );
-
-			// revert object geometry's faces
-
-			if ( facesSearch.length > 0 ) {
-
-				object.geometry.faces = facesAll;
-
-			}
-
-		} else {
-
-			intersects = this.intersectObject( object, recursive );
-
-		}
-
-		return intersects;
-
-	};
-
-	THREE.Raycaster.prototype.intersectOctreeObjects = function ( objects, recursive ) {
-
-		var i, il,
-			intersects = [];
-
-		for ( i = 0, il = objects.length; i < il; i ++ ) {
-
-			intersects = intersects.concat( this.intersectOctreeObject( objects[ i ], recursive ) );
-
-		}
-
-		// we should sort it, the elements in it aren't arranged by distance.
-		intersects.sort( function( a, b ) {
-			return a.distance - b.distance;
-		} );
-
-		return intersects;
-
-	};
-
-}( THREE ) );

+ 0 - 250
examples/webgl_octree.html

@@ -1,250 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-	<head>
-		<title>three.js webgl - octree</title>
-		<meta charset="utf-8">
-		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
-		<style>
-			body {
-				font-family: Monospace;
-				background-color: #f0f0f0;
-				margin: 0px;
-				overflow: hidden;
-			}
-		</style>
-	</head>
-	<body>
-
-		<script type="text/javascript" src="../build/three.js"></script>
-		<script type="text/javascript" src="js/Octree.js"></script>
-		<script>
-
-			var camera,
-				scene,
-				renderer,
-				octree,
-				geometry = new THREE.BoxBufferGeometry( 50, 50, 50 ),
-				mesh,
-				meshes = [],
-				meshesSearch = [],
-				meshCountMax = 100,
-				radius = 500,
-				radiusMax = radius * 10,
-				radiusMaxHalf = radiusMax * 0.5,
-				radiusSearch = 400,
-				searchMesh,
-				base = new THREE.Color( 0xff00ff ),
-				found = new THREE.Color( 0x00ff00 ),
-				adding = true,
-				rayCaster = new THREE.Raycaster(),
-				origin = new THREE.Vector3(),
-				direction = new THREE.Vector3();
-
-			init();
-			animate();
-
-			function init() {
-
-				// standard three scene, camera, renderer
-
-				scene = new THREE.Scene();
-				scene.background = new THREE.Color( 0xf0f0f0 );
-
-				camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, radius * 100 );
-				scene.add( camera );
-
-				renderer = new THREE.WebGLRenderer();
-				renderer.setPixelRatio( window.devicePixelRatio );
-				renderer.setSize( window.innerWidth, window.innerHeight );
-				document.body.appendChild( renderer.domElement );
-
-				// create octree
-
-				octree = new THREE.Octree( {
-					// when undeferred = true, objects are inserted immediately
-					// instead of being deferred until next octree.update() call
-					// this may decrease performance as it forces a matrix update
-					undeferred: false,
-					// set the max depth of tree
-					depthMax: Infinity,
-					// max number of objects before nodes split or merge
-					objectsThreshold: 8,
-					// percent between 0 and 1 that nodes will overlap each other
-					// helps insert objects that lie over more than one node
-					overlapPct: 0.15,
-					// pass the scene to visualize the octree
-					scene: scene
-				} );
-
-				// create object to show search radius and add to scene
-
-				searchMesh = new THREE.Mesh(
-					new THREE.SphereBufferGeometry( radiusSearch ),
-					new THREE.MeshBasicMaterial( { color: 0x00FF00, transparent: true, opacity: 0.4 } )
-				);
-				scene.add( searchMesh );
-
-				// info
-
-				var info = document.createElement( 'div' );
-				info.style.position = 'absolute';
-				info.style.top = '0';
-				info.style.width = '100%';
-				info.style.textAlign = 'center';
-				info.style.padding = '10px';
-				info.style.background = '#FFFFFF';
-				info.innerHTML = '<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> webgl - octree (sparse & dynamic) - by <a href="http://github.com/collinhover/threeoctree" target="_blank" rel="noopener">collinhover</a>';
-				document.body.appendChild( info );
-
-			}
-
-			function animate() {
-
-				// note: three.js includes requestAnimationFrame shim
-				requestAnimationFrame( animate );
-
-				// modify octree structure by adding/removing objects
-
-				modifyOctree();
-
-				// search octree at random location
-
-				searchOctree();
-
-				// render results
-
-				render();
-
-				// update octree to add deferred objects
-
-				octree.update();
-
-			}
-
-			function modifyOctree() {
-
-				// if is adding objects to octree
-
-				if ( adding === true ) {
-
-					// create new object
-
-					mesh = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( { color: new THREE.Color( base ) } ) );
-
-					// give new object a random position in radius
-
-					mesh.position.set(
-						Math.random() * radiusMax - radiusMaxHalf,
-						Math.random() * radiusMax - radiusMaxHalf,
-						Math.random() * radiusMax - radiusMaxHalf
-					);
-
-					// add new object to octree and scene
-
-					octree.add( mesh );
-					scene.add( mesh );
-
-					// store object for later
-
-					meshes.push( mesh );
-
-					// if at max, stop adding
-
-					if ( meshes.length === meshCountMax ) {
-
-						adding = false;
-
-					}
-
-				} else { // else remove objects from octree
-
-					// get object
-
-					mesh = meshes.shift();
-
-					// remove from scene and octree
-
-					scene.remove( mesh );
-					octree.remove( mesh );
-
-					// if no more objects, start adding
-
-					if ( meshes.length === 0 ) {
-
-						adding = true;
-
-					}
-
-				}
-
-				/*
-
-				// octree details to console
-
-				console.log( ' OCTREE: ', octree );
-				console.log( ' ... depth ', octree.depth, ' vs depth end?', octree.depth_end() );
-				console.log( ' ... num nodes: ', octree.node_count_end() );
-				console.log( ' ... total objects: ', octree.object_count_end(), ' vs tree objects length: ', octree.objects.length );
-
-				// print full octree structure to console
-
-				octree.to_console();
-
-				*/
-
-			}
-
-			function searchOctree() {
-
-				var i, il;
-
-				// revert previous search objects to base color
-
-				for ( i = 0, il = meshesSearch.length; i < il; i ++ ) {
-
-					meshesSearch[ i ].object.material.color.copy( base );
-
-				}
-
-				// new search position
-				searchMesh.position.set(
-					Math.random() * radiusMax - radiusMaxHalf,
-					Math.random() * radiusMax - radiusMaxHalf,
-					Math.random() * radiusMax - radiusMaxHalf
-				);
-
-				// search octree from search mesh position with search radius
-				// optional third parameter: boolean, if should sort results by object when using faces in octree
-				// optional fourth parameter: vector3, direction of search when using ray (assumes radius is distance/far of ray)
-
-				origin.copy( searchMesh.position );
-				direction.set( Math.random() * 2 - 1, Math.random() * 2 - 1, Math.random() * 2 - 1 ).normalize();
-				rayCaster.set( origin, direction );
-				meshesSearch = octree.search( rayCaster.ray.origin, radiusSearch, true, rayCaster.ray.direction );
-				rayCaster.intersectOctreeObjects( meshesSearch );
-
-				// set color of all meshes found in search
-
-				for ( i = 0, il = meshesSearch.length; i < il; i ++ ) {
-
-					meshesSearch[ i ].object.material.color.copy( found );
-
-				}
-
-			}
-
-			function render() {
-
-				var timer = - Date.now() / 5000;
-
-				camera.position.x = Math.cos( timer ) * 10000;
-				camera.position.z = Math.sin( timer ) * 10000;
-				camera.lookAt( scene.position );
-
-				renderer.render( scene, camera );
-
-			}
-
-		</script>
-	</body>
-</html>

+ 0 - 360
examples/webgl_octree_raycasting.html

@@ -1,360 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-	<title>three.js webgl - octree raycasting</title>
-	<meta charset="utf-8">
-	<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
-	<style>
-		body {
-			font-family: Monospace;
-			background-color: #f0f0f0;
-			margin: 0px;
-			overflow: hidden;
-		}
-	</style>
-
-</head>
-
-<body>
-
-	<script type="text/javascript" src="../build/three.js"></script>
-	<script type="text/javascript" src="js/Octree.js"></script>
-	<script type="text/javascript" src="js/controls/TrackballControls.js"></script>
-	<script type="text/javascript" src="js/libs/stats.min.js"></script>
-	<script>
-
-		var camera, scene, renderer;
-
-		var controls, stats;
-
-		var tracker;
-
-		var octree;
-
-		var objects = [];
-		var totalFaces = 0;
-
-		var simpleMeshCount = 5000;
-		var radius = 100;
-		var radiusMax = radius * 10;
-		var radiusMaxHalf = radiusMax * 0.5;
-
-		var baseColor = 0x333333;
-		var intersectColor = 0x00D66B;
-
-		var useOctree = true;
-
-		var raycaster = new THREE.Raycaster();
-		var mouse = new THREE.Vector2();
-		var intersected;
-
-		init();
-		animate();
-
-		function init() {
-
-			// standard three scene, camera, renderer
-
-			scene = new THREE.Scene();
-
-			camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, radius * 100 );
-			camera.position.z = radius * 10;
-			scene.add( camera );
-
-			renderer = new THREE.WebGLRenderer();
-			renderer.setPixelRatio( window.devicePixelRatio );
-			renderer.setSize( window.innerWidth, window.innerHeight );
-			document.body.appendChild( renderer.domElement );
-
-			// create octree
-
-			octree = new THREE.Octree( {
-				// uncomment below to see the octree (may kill the fps)
-				//scene: scene,
-				// when undeferred = true, objects are inserted immediately
-				// instead of being deferred until next octree.update() call
-				// this may decrease performance as it forces a matrix update
-				undeferred: false,
-				// set the max depth of tree
-				depthMax: Infinity,
-				// max number of objects before nodes split or merge
-				objectsThreshold: 8,
-				// percent between 0 and 1 that nodes will overlap each other
-				// helps insert objects that lie over more than one node
-				overlapPct: 0.15
-			} );
-
-			// lights
-
-			var ambient = new THREE.AmbientLight( 0x101010 );
-			scene.add( ambient );
-
-			var directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
-			directionalLight.position.set( 1, 1, 2 ).normalize();
-			scene.add( directionalLight );
-
-			// create all objects
-
-			var simpleGeometry = new THREE.BoxGeometry( 1, 1, 1 );
-
-			for ( var i = 0; i < simpleMeshCount - 1; i ++ ) {
-
-				totalFaces += simpleGeometry.faces.length;
-
-				var simpleMaterial = new THREE.MeshBasicMaterial();
-				simpleMaterial.color.setHex( baseColor );
-
-				modifyOctree( simpleGeometry, simpleMaterial, false, true, true, true );
-
-			}
-
-			// camera controls
-
-			controls = new THREE.TrackballControls( camera );
-			controls.rotateSpeed = 1.0;
-			controls.zoomSpeed = 1.2;
-			controls.panSpeed = 0.8;
-			controls.noZoom = false;
-			controls.noPan = false;
-			controls.staticMoving = true;
-			controls.dynamicDampingFactor = 0.3;
-
-			// info
-
-			var info = document.createElement( 'div' );
-			info.style.position = 'absolute';
-			info.style.top = '0';
-			info.style.width = '100%';
-			info.style.textAlign = 'center';
-			info.style.padding = '10px';
-			info.style.background = '#FFFFFF';
-			info.innerHTML = '<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> webgl - octree (raycasting performance) - by <a href="http://github.com/collinhover/threeoctree" target="_blank" rel="noopener">collinhover</a>)</small>';
-			document.body.appendChild( info );
-
-			// stats
-
-			stats = new Stats();
-			document.body.appendChild( stats.dom );
-
-			// bottom container
-
-			var container = document.createElement( 'div' );
-			container.style.position = 'absolute';
-			container.style.bottom = '0';
-			container.style.width = '100%';
-			container.style.textAlign = 'center';
-			document.body.appendChild( container );
-
-			// tracker
-
-			tracker = document.createElement( 'div' );
-			tracker.style.width = '100%';
-			tracker.style.padding = '10px';
-			tracker.style.background = '#FFFFFF';
-			container.appendChild( tracker );
-
-			// octree use toggle
-
-			var toggle = document.createElement( 'div' );
-			toggle.style.position = 'absolute';
-			toggle.style.bottom = '100%';
-			toggle.style.width = '100%';
-			toggle.style.padding = '10px';
-			toggle.style.background = '#FFFFFF';
-			container.appendChild( toggle );
-
-			var checkbox = document.createElement( 'input' );
-			checkbox.type = "checkbox";
-			checkbox.name = "octreeToggle";
-			checkbox.value = "value";
-			checkbox.id = "octreeToggle";
-			checkbox.checked = true;
-
-			var label = document.createElement( 'label' );
-			label.htmlFor = "octreeToggle";
-			label.appendChild( document.createTextNode( 'Use Octree' ) );
-
-			toggle.appendChild( checkbox );
-			toggle.appendChild( label );
-
-			// events
-
-			checkbox.addEventListener( 'click', toggleOctree, false );
-			renderer.domElement.addEventListener( 'mousemove', onDocumentMouseMove, false );
-
-			window.addEventListener( 'resize', onWindowResize, false );
-
-		}
-
-		function toggleOctree() {
-
-			useOctree = ! useOctree;
-
-		}
-
-		function animate() {
-
-			// note: three.js includes requestAnimationFrame shim
-
-			requestAnimationFrame( animate );
-
-			render();
-
-			stats.update();
-
-		}
-
-		function render() {
-
-			controls.update();
-
-			renderer.render( scene, camera );
-
-			// update octree post render
-			// this ensures any objects being added
-			// have already had their matrices updated
-
-			octree.update();
-
-		}
-
-		function modifyOctree( geometry, material, useFaces, randomPosition, randomRotation, randomScale ) {
-
-			var mesh;
-
-			if ( geometry ) {
-
-				// create new object
-
-				mesh = new THREE.Mesh( geometry, material );
-
-				// give new object a random position, rotation, and scale
-
-				if ( randomPosition ) {
-
-					mesh.position.set( Math.random() * radiusMax - radiusMaxHalf, Math.random() * radiusMax - radiusMaxHalf, Math.random() * radiusMax - radiusMaxHalf );
-
-				}
-
-				if ( randomRotation ) {
-
-					mesh.rotation.set( Math.random() * 2 * Math.PI, Math.random() * 2 * Math.PI, Math.random() * 2 * Math.PI );
-
-				}
-
-				if ( randomScale ) {
-
-					mesh.scale.x = mesh.scale.y = mesh.scale.z = Math.random() * radius * 0.1 + radius * 0.05;
-
-				}
-
-				// add new object to octree and scene
-				// NOTE: octree object insertion is deferred until after the next render cycle
-
-				octree.add( mesh, { useFaces: useFaces } );
-				scene.add( mesh );
-
-				// store object
-
-				objects.push( mesh );
-
-				/*
-
-				// octree details to console
-
-				console.log( ' ============================================================================================================');
-				console.log( ' OCTREE: ', octree );
-				console.log( ' ... depth ', octree.depth, ' vs depth end?', octree.depthEnd() );
-				console.log( ' ... num nodes: ', octree.nodeCountEnd() );
-				console.log( ' ... total objects: ', octree.objectCountEnd(), ' vs tree objects length: ', octree.objects.length );
-				console.log( ' ============================================================================================================');
-				console.log( ' ');
-
-				// print full octree structure to console
-
-				octree.toConsole();
-
-				*/
-
-			}
-
-		}
-
-		function onWindowResize() {
-
-			camera.aspect = window.innerWidth / window.innerHeight;
-			camera.updateProjectionMatrix();
-
-			renderer.setSize( window.innerWidth, window.innerHeight );
-
-		}
-
-		function onDocumentMouseMove( event ) {
-
-			event.preventDefault();
-
-			mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
-			mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
-
-			raycaster.setFromCamera( mouse, camera );
-
-			var octreeObjects;
-			var numObjects;
-			var numFaces = 0;
-			var intersections;
-
-			if ( useOctree ) {
-
-				octreeObjects = octree.search( raycaster.ray.origin, raycaster.ray.far, true, raycaster.ray.direction );
-
-				intersections = raycaster.intersectOctreeObjects( octreeObjects );
-
-				numObjects = octreeObjects.length;
-
-				for ( var i = 0, il = numObjects; i < il; i ++ ) {
-
-					numFaces += octreeObjects[ i ].faces.length;
-
-				}
-
-			} else {
-
-				intersections = raycaster.intersectObjects( objects );
-				numObjects = objects.length;
-				numFaces = totalFaces;
-
-			}
-
-			if ( intersections.length > 0 ) {
-
-				if ( intersected != intersections[ 0 ].object ) {
-
-					if ( intersected ) intersected.material.color.setHex( baseColor );
-
-					intersected = intersections[ 0 ].object;
-					intersected.material.color.setHex( intersectColor );
-
-				}
-
-				document.body.style.cursor = 'pointer';
-
-			} else if ( intersected ) {
-
-				intersected.material.color.setHex( baseColor );
-				intersected = null;
-
-				document.body.style.cursor = 'auto';
-
-			}
-
-			// update tracker
-
-			tracker.innerHTML = ( useOctree ? 'Octree search' : 'Search without octree' ) + ' using infinite ray from camera found [ ' + numObjects + ' / ' + objects.length + ' ] objects, [ ' + numFaces + ' / ' + totalFaces + ' ] faces, and [ ' + intersections.length + ' ] intersections.';
-
-		}
-
-	</script>
-
-</body>
-
-</html>