Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
205 changes: 105 additions & 100 deletions examples/js/interactive/SelectionBox.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,114 +3,119 @@
* This is a class to check whether objects are in a selection area in 3D space
*/

function SelectionBox ( camera, scene, deep ) {

this.camera = camera;
this.scene = scene;
this.startPoint = new THREE.Vector3();
this.endPoint = new THREE.Vector3();
this.collection = [];
this.deep = deep || Number.MAX_VALUE;

}

SelectionBox.prototype.select = function ( startPoint, endPoint ) {

this.startPoint = startPoint || this.startPoint;
this.endPoint = endPoint || this.endPoint;
this.collection = [];

var boxSelectionFrustum = this.createFrustum( this.startPoint, this.endPoint );
this.searchChildInFrustum( boxSelectionFrustum, this.scene );

return this.collection;

}

SelectionBox.prototype.createFrustum = function ( startPoint, endPoint ) {

startPoint = startPoint || this.startPoint;
endPoint = endPoint || this.endPoint

this.camera.updateProjectionMatrix();
this.camera.updateMatrixWorld();
this.camera.updateMatrix();

var tmpPoint = startPoint.clone();
tmpPoint.x = Math.min( startPoint.x, endPoint.x );
tmpPoint.y = Math.max( startPoint.y, endPoint.y );
endPoint.x = Math.max( startPoint.x, endPoint.x );
endPoint.y = Math.min( startPoint.y, endPoint.y );

var vecNear = this.camera.position.clone();
var vecTopLeft = tmpPoint.clone();
var vecTopRight = new THREE.Vector3( endPoint.x, tmpPoint.y, 0 );
var vecDownRight = endPoint.clone();
var vecDownLeft = new THREE.Vector3( tmpPoint.x, endPoint.y, 0 );
vecTopLeft.unproject( this.camera );
vecTopRight.unproject( this.camera );
vecDownRight.unproject( this.camera );
vecDownLeft.unproject( this.camera );

var vectemp1 = vecTopLeft.clone().sub( vecNear );
var vectemp2 = vecTopRight.clone().sub( vecNear );
var vectemp3 = vecDownRight.clone().sub( vecNear );
vectemp1.normalize();
vectemp2.normalize();
vectemp3.normalize();

vectemp1.multiplyScalar( this.deep );
vectemp2.multiplyScalar( this.deep );
vectemp3.multiplyScalar( this.deep );
vectemp1.add( vecNear );
vectemp2.add( vecNear );
vectemp3.add( vecNear );

var planeTop = new THREE.Plane();
planeTop.setFromCoplanarPoints( vecNear, vecTopLeft, vecTopRight );
var planeRight = new THREE.Plane();
planeRight.setFromCoplanarPoints( vecNear, vecTopRight, vecDownRight );
var planeDown = new THREE.Plane();
planeDown.setFromCoplanarPoints( vecDownRight, vecDownLeft, vecNear );
var planeLeft = new THREE.Plane();
planeLeft.setFromCoplanarPoints( vecDownLeft, vecTopLeft, vecNear );
var planeFront = new THREE.Plane();
planeFront.setFromCoplanarPoints( vecTopRight, vecDownRight, vecDownLeft );
var planeBack = new THREE.Plane();
planeBack.setFromCoplanarPoints( vectemp3, vectemp2, vectemp1 );
planeBack.normal = planeBack.normal.multiplyScalar( -1 );

return new THREE.Frustum( planeTop, planeRight, planeDown, planeLeft, planeFront, planeBack );

}

SelectionBox.prototype.searchChildInFrustum = function ( frustum, object ) {

if ( object instanceof THREE.Mesh ) {

if ( object.material !== undefined ) {

object.geometry.computeBoundingSphere();
var center = object.geometry.boundingSphere.center.clone().applyMatrix4( object.matrixWorld );

if ( frustum.containsPoint( center ) ) {

this.collection.push( object );
THREE.SelectionBox = ( function () {

var frustum = new THREE.Frustum();
var center = new THREE.Vector3();

function SelectionBox( camera, scene, deep ) {

this.camera = camera;
this.scene = scene;
this.startPoint = new THREE.Vector3();
this.endPoint = new THREE.Vector3();
this.collection = [];
this.deep = deep || Number.MAX_VALUE;

}

SelectionBox.prototype.select = function ( startPoint, endPoint ) {

this.startPoint = startPoint || this.startPoint;
this.endPoint = endPoint || this.endPoint;
this.collection = [];

this.updateFrustum( this.startPoint, this.endPoint );
this.searchChildInFrustum( frustum, this.scene );

return this.collection;

};

SelectionBox.prototype.updateFrustum = function ( startPoint, endPoint ) {

startPoint = startPoint || this.startPoint;
endPoint = endPoint || this.endPoint;

this.camera.updateProjectionMatrix();
this.camera.updateMatrixWorld();

var tmpPoint = startPoint.clone();
tmpPoint.x = Math.min( startPoint.x, endPoint.x );
tmpPoint.y = Math.max( startPoint.y, endPoint.y );
endPoint.x = Math.max( startPoint.x, endPoint.x );
endPoint.y = Math.min( startPoint.y, endPoint.y );

var vecNear = this.camera.position.clone();
var vecTopLeft = tmpPoint.clone();
var vecTopRight = new THREE.Vector3( endPoint.x, tmpPoint.y, 0 );
var vecDownRight = endPoint.clone();
var vecDownLeft = new THREE.Vector3( tmpPoint.x, endPoint.y, 0 );
vecTopLeft.unproject( this.camera );
vecTopRight.unproject( this.camera );
vecDownRight.unproject( this.camera );
vecDownLeft.unproject( this.camera );

var vectemp1 = vecTopLeft.clone().sub( vecNear );
var vectemp2 = vecTopRight.clone().sub( vecNear );
var vectemp3 = vecDownRight.clone().sub( vecNear );
vectemp1.normalize();
vectemp2.normalize();
vectemp3.normalize();

vectemp1.multiplyScalar( this.deep );
vectemp2.multiplyScalar( this.deep );
vectemp3.multiplyScalar( this.deep );
vectemp1.add( vecNear );
vectemp2.add( vecNear );
vectemp3.add( vecNear );

var planes = frustum.planes;

planes[ 0 ].setFromCoplanarPoints( vecNear, vecTopLeft, vecTopRight );
planes[ 1 ].setFromCoplanarPoints( vecNear, vecTopRight, vecDownRight );
planes[ 2 ].setFromCoplanarPoints( vecDownRight, vecDownLeft, vecNear );
planes[ 3 ].setFromCoplanarPoints( vecDownLeft, vecTopLeft, vecNear );
planes[ 4 ].setFromCoplanarPoints( vecTopRight, vecDownRight, vecDownLeft );
planes[ 5 ].setFromCoplanarPoints( vectemp3, vectemp2, vectemp1 );
planes[ 5 ].normal.multiplyScalar( - 1 );

};

SelectionBox.prototype.searchChildInFrustum = function ( frustum, object ) {

if ( object.isMesh ) {

if ( object.material !== undefined ) {

object.geometry.computeBoundingSphere();

center.copy( object.geometry.boundingSphere.center );

center.applyMatrix4( object.matrixWorld );

if ( frustum.containsPoint( center ) ) {

this.collection.push( object );

}

}

}

}
if ( object.children.length > 0 ) {

if ( object.children.length > 0 ) {
for ( var x = 0; x < object.children.length; x ++ ) {

for ( var x = 0; x < object.children.length; x++ ) {
this.searchChildInFrustum( frustum, object.children[ x ] );

this.searchChildInFrustum( frustum, object.children[x] );
}

}

}

}
};

return SelectionBox;

} )();
110 changes: 60 additions & 50 deletions examples/js/interactive/SelectionHelper.js
Original file line number Diff line number Diff line change
@@ -1,73 +1,83 @@
function SelectionHelper ( selectionBox, renderer, cssClassName ) {
/**
* @author HypnosNova / https://www.threejs.org.cn/gallery
*/

this.element = document.createElement( "div" );
this.element.classList.add( cssClassName );
this.element.style.pointerEvents = "none";
THREE.SelectionHelper = ( function () {

this.renderer = renderer;
function SelectionHelper( selectionBox, renderer, cssClassName ) {

this.startPoint = { x: 0, y: 0 };
this.pointTopLeft = { x: 0, y: 0 };
this.pointBottomRight = { x: 0, y: 0 };
this.element = document.createElement( 'div' );
this.element.classList.add( cssClassName );
this.element.style.pointerEvents = 'none';

this.isDown = false;
this.renderer = renderer;

this.renderer.domElement.addEventListener( "mousedown", function ( event ) {

this.isDown = true;
this.onSelectStart( event );
this.startPoint = { x: 0, y: 0 };
this.pointTopLeft = { x: 0, y: 0 };
this.pointBottomRight = { x: 0, y: 0 };

}.bind( this ), false );
this.isDown = false;

this.renderer.domElement.addEventListener( "mousemove", function ( event ) {
this.renderer.domElement.addEventListener( 'mousedown', function ( event ) {

if ( this.isDown ) {
this.isDown = true;
this.onSelectStart( event );

this.onSelectMove( event );
}.bind( this ), false );

}
this.renderer.domElement.addEventListener( 'mousemove', function ( event ) {

}.bind( this ), false );
if ( this.isDown ) {

this.renderer.domElement.addEventListener( "mouseup", function ( event ) {
this.onSelectMove( event );

this.isDown = false;
this.onSelectOver( event );
}

}.bind( this ), false );

this.renderer.domElement.addEventListener( 'mouseup', function ( event ) {

this.isDown = false;
this.onSelectOver( event );

}.bind( this ), false );

}

SelectionHelper.prototype.onSelectStart = function ( event ) {

this.renderer.domElement.parentElement.appendChild( this.element );

this.element.style.left = event.clientX + 'px';
this.element.style.top = event.clientY + 'px';
this.element.style.width = '0px';
this.element.style.height = '0px';

this.startPoint.x = event.clientX;
this.startPoint.y = event.clientY;

}.bind( this ), false );

}
};

SelectionHelper.prototype.onSelectStart = function ( event ) {

this.renderer.domElement.parentElement.appendChild( this.element );
SelectionHelper.prototype.onSelectMove = function ( event ) {

this.element.style.left = event.clientX + "px";
this.element.style.top = event.clientY + "px";
this.element.style.width = "0px";
this.element.style.height = "0px";
this.pointBottomRight.x = Math.max( this.startPoint.x, event.clientX );
this.pointBottomRight.y = Math.max( this.startPoint.y, event.clientY );
this.pointTopLeft.x = Math.min( this.startPoint.x, event.clientX );
this.pointTopLeft.y = Math.min( this.startPoint.y, event.clientY );

this.startPoint.x = event.clientX;
this.startPoint.y = event.clientY;
this.element.style.left = this.pointTopLeft.x + 'px';
this.element.style.top = this.pointTopLeft.y + 'px';
this.element.style.width = ( this.pointBottomRight.x - this.pointTopLeft.x ) + 'px';
this.element.style.height = ( this.pointBottomRight.y - this.pointTopLeft.y ) + 'px';

}
};

SelectionHelper.prototype.onSelectMove = function ( event ) {
SelectionHelper.prototype.onSelectOver = function () {

this.pointBottomRight.x = Math.max( this.startPoint.x, event.clientX );
this.pointBottomRight.y = Math.max( this.startPoint.y, event.clientY );
this.pointTopLeft.x = Math.min( this.startPoint.x, event.clientX );
this.pointTopLeft.y = Math.min( this.startPoint.y, event.clientY );
this.element.parentElement.removeChild( this.element );

this.element.style.left = this.pointTopLeft.x + "px";
this.element.style.top = this.pointTopLeft.y + "px";
this.element.style.width = ( this.pointBottomRight.x - this.pointTopLeft.x ) + "px";
this.element.style.height = ( this.pointBottomRight.y - this.pointTopLeft.y ) + "px";

}
};

SelectionHelper.prototype.onSelectOver = function ( event ) {
return SelectionHelper;

this.element.parentElement.removeChild( this.element );

}
} )();
Loading