Quellcode durchsuchen

JSM: Added module and TS files for SelectionBox and SelectionHelper.

Mugen87 vor 6 Jahren
Ursprung
Commit
ba9c915af7

+ 6 - 0
docs/manual/en/introduction/Import-via-modules.html

@@ -134,6 +134,12 @@
 						<li>TeapotBufferGeometry</li>
 					</ul>
 				</li>
+				<li>interactive
+					<ul>
+						<li>SelectionBox</li>
+						<li>SelectionHelper</li>
+					</ul>
+				</li>
 				<li>lines
 					<ul>
 						<li>Line2</li>

+ 22 - 0
examples/jsm/interactive/SelectionBox.d.ts

@@ -0,0 +1,22 @@
+import {
+  Camera,
+  Frustum,
+  Mesh,
+  Object3D,
+  Scene,
+  Vector3
+} from '../../../src/Three';
+
+export class SelectionBox  {
+  constructor(camera: Camera, scene: Scene, deep?: number);
+  camera: Camera;
+  collection: Mesh[];
+  deep: number;
+  endPoint: Vector3;
+  scene: Scene;
+  startPoint: Vector3;
+
+  select(startPoint: Vector3, endPoint: Vector3): Mesh[];
+  updateFrustum(startPoint: Vector3, endPoint: Vector3): void;
+  searchChildInFrustum(frustum: Frustum, object: Object3D): void;
+}

+ 128 - 0
examples/jsm/interactive/SelectionBox.js

@@ -0,0 +1,128 @@
+/**
+ * @author HypnosNova / https://www.threejs.org.cn/gallery
+ * This is a class to check whether objects are in a selection area in 3D space
+ */
+
+import {
+	Frustum,
+	Vector3
+} from "../../../build/three.module.js";
+
+var SelectionBox = ( function () {
+
+	var frustum = new Frustum();
+	var center = new Vector3();
+
+	function SelectionBox( camera, scene, deep ) {
+
+		this.camera = camera;
+		this.scene = scene;
+		this.startPoint = new Vector3();
+		this.endPoint = new 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 Vector3( endPoint.x, tmpPoint.y, 0 );
+		var vecDownRight = endPoint.clone();
+		var vecDownLeft = new 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 ) {
+
+			for ( var x = 0; x < object.children.length; x ++ ) {
+
+				this.searchChildInFrustum( frustum, object.children[ x ] );
+
+			}
+
+		}
+
+	};
+
+	return SelectionBox;
+
+} )();
+
+export { SelectionBox };

+ 20 - 0
examples/jsm/interactive/SelectionHelper.d.ts

@@ -0,0 +1,20 @@
+import {
+  WebGLRenderer,
+  Vector2
+} from '../../../src/Three';
+
+import { SelectionBox } from './SelectionBox';
+
+export class SelectionHelper {
+  constructor(selectionBox: SelectionBox, renderer: WebGLRenderer, cssClassName: string);
+  element: HTMLElement;
+  isDown: boolean;
+  pointBottomRight: Vector2;
+  pointTopLeft: Vector2;
+  renderer: WebGLRenderer;
+  startPoint: Vector2;
+
+  onSelectStart(event: Event): void;
+  onSelectMove(event: Event): void;
+  onSelectOver(event: Event): void;
+}

+ 89 - 0
examples/jsm/interactive/SelectionHelper.js

@@ -0,0 +1,89 @@
+/**
+ * @author HypnosNova / https://www.threejs.org.cn/gallery
+ */
+
+import {
+	Vector2
+} from "../../../build/three.module.js";
+
+var SelectionHelper = ( function () {
+
+	function SelectionHelper( selectionBox, renderer, cssClassName ) {
+
+		this.element = document.createElement( 'div' );
+		this.element.classList.add( cssClassName );
+		this.element.style.pointerEvents = 'none';
+
+		this.renderer = renderer;
+
+		this.startPoint = new Vector2();
+		this.pointTopLeft = new Vector2();
+		this.pointBottomRight = new Vector2();
+
+		this.isDown = false;
+
+		this.renderer.domElement.addEventListener( 'mousedown', function ( event ) {
+
+			this.isDown = true;
+			this.onSelectStart( event );
+
+		}.bind( this ), false );
+
+		this.renderer.domElement.addEventListener( 'mousemove', function ( event ) {
+
+			if ( this.isDown ) {
+
+				this.onSelectMove( 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;
+
+	};
+
+	SelectionHelper.prototype.onSelectMove = function ( event ) {
+
+		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.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 () {
+
+		this.element.parentElement.removeChild( this.element );
+
+	};
+
+	return SelectionHelper;
+
+} )();
+
+export { SelectionHelper };

+ 3 - 0
utils/modularize.js

@@ -49,6 +49,9 @@ var files = [
 	{ path: 'geometries/ParametricGeometries.js', dependencies: [], ignoreList: [] },
 	{ path: 'geometries/TeapotBufferGeometry.js', dependencies: [], ignoreList: [] },
 
+	{ path: 'interactive/SelectionBox.js', dependencies: [], ignoreList: [] },
+	{ path: 'interactive/SelectionHelper.js', dependencies: [], ignoreList: [] },
+
 	{ path: 'lines/Line2.js', dependencies: [ { name: 'LineSegments2', path: 'lines/LineSegments2.js' }, { name: 'LineGeometry', path: 'lines/LineGeometry.js' }, { name: 'LineMaterial', path: 'lines/LineMaterial.js' } ], ignoreList: [] },
 	{ path: 'lines/LineGeometry.js', dependencies: [ { name: 'LineSegmentsGeometry', path: 'lines/LineSegmentsGeometry.js' } ], ignoreList: [] },
 	{ path: 'lines/LineMaterial.js', dependencies: [], ignoreList: [] },