Viewport.js 9.6 KB
Newer Older
M
Mr.doob 已提交
1 2 3 4 5 6 7
var Viewport = function ( signals ) {

	var container = new UI.Panel( 'absolute' );
	container.setBackgroundColor( '#aaa' );

	//

8 9
	var objects = [];

M
Mr.doob 已提交
10 11
	var sceneHelpers = new THREE.Scene();

M
Mr.doob 已提交
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
	var size = 500, step = 25;
	var geometry = new THREE.Geometry();
	var material = new THREE.LineBasicMaterial( { vertexColors: THREE.VertexColors } );
	var color1 = new THREE.Color( 0x444444 ), color2 = new THREE.Color( 0x888888 );

	for ( var i = - size; i <= size; i += step ) {

		geometry.vertices.push( new THREE.Vector3( -size, 0, i ) );
		geometry.vertices.push( new THREE.Vector3(  size, 0, i ) );

		geometry.vertices.push( new THREE.Vector3( i, 0, -size ) );
		geometry.vertices.push( new THREE.Vector3( i, 0,  size ) );

		var color = i === 0 ? color1 : color2;

		geometry.colors.push( color, color, color, color );

	}

	var grid = new THREE.Line( geometry, material, THREE.LinePieces );
	sceneHelpers.add( grid );

34
	var selectionBox = new THREE.Mesh( new THREE.CubeGeometry( 1, 1, 1 ), new THREE.MeshBasicMaterial( { color: 0xffff00, wireframe: true } ) );
M
Mr.doob 已提交
35
	selectionBox.matrixAutoUpdate = false;
36 37 38
	selectionBox.visible = false;
	sceneHelpers.add( selectionBox );

39
	var selectionAxis = new THREE.AxisHelper( 100 );
M
Mr.doob 已提交
40
	selectionAxis.material.depthTest = false;
M
Mr.doob 已提交
41
	selectionAxis.material.transparent = true;
M
Mr.doob 已提交
42
	selectionAxis.matrixAutoUpdate = false;
M
Mr.doob 已提交
43
	selectionAxis.visible = false;
M
Mr.doob 已提交
44 45
	sceneHelpers.add( selectionAxis );

M
Mr.doob 已提交
46
	//
M
Mr.doob 已提交
47 48 49 50 51 52

	var scene = new THREE.Scene();

	var camera = new THREE.PerspectiveCamera( 50, 1, 1, 5000 );
	camera.position.set( 500, 250, 500 );
	camera.lookAt( scene.position );
53
	scene.add( camera );
M
Mr.doob 已提交
54

55 56 57
	var light1 = new THREE.DirectionalLight( 0xffffff );
	light1.position.set( 1, 0.5, 0 ).normalize();
	scene.add( light1 );
M
Mr.doob 已提交
58

59 60 61
	var light2 = new THREE.DirectionalLight( 0xffffff, 0.5 );
	light2.position.set( - 1, - 0.5, 0 ).normalize();
	scene.add( light2 );
62

63
	// default objects names
M
Mr.doob 已提交
64

65 66
	camera.name = "Camera";

67 68
	light1.name = "Light 1";
	light1.target.name = "Target for light 1";
69

70 71
	light2.name = "Light 2";
	light2.target.name = "Target for light 2";
72
	signals.sceneChanged.dispatch( scene );
M
Mr.doob 已提交
73

74 75
	// object picking

M
Mr.doob 已提交
76 77 78
	var intersectionPlane = new THREE.Mesh( new THREE.PlaneGeometry( 2000, 2000, 8, 8 ) );
	intersectionPlane.visible = false;
	sceneHelpers.add( intersectionPlane );
79

M
Mr.doob 已提交
80
	var ray = new THREE.Ray();
81
	var projector = new THREE.Projector();
M
Mr.doob 已提交
82 83
	var offset = new THREE.Vector3();
	var picked = null;
84

85 86 87
	// events

	var onMouseDown = function ( event ) {
88 89 90

		event.preventDefault();

M
Mr.doob 已提交
91 92 93 94 95
		var vector = new THREE.Vector3(
			( ( event.clientX - container.dom.offsetLeft ) / container.dom.offsetWidth ) * 2 - 1,
			- ( ( event.clientY - container.dom.offsetTop ) / container.dom.offsetHeight ) * 2 + 1,
			0.5
		);
96

M
Mr.doob 已提交
97 98 99 100 101 102 103 104 105 106
		projector.unprojectVector( vector, camera );

		ray.set( camera.position, vector.subSelf( camera.position ).normalize() );

		var intersects = ray.intersectObjects( objects, true );

		if ( intersects.length > 0 ) {

			controls.enabled = false;

107 108 109
			intersectionPlane.position.copy( intersects[ 0 ].object.position );
			intersectionPlane.lookAt( camera.position );

M
Mr.doob 已提交
110
			picked = intersects[ 0 ].object;
111
			selected = picked;
M
Mr.doob 已提交
112

113
			signals.objectSelected.dispatch( selected );
M
Mr.doob 已提交
114 115 116 117

			var intersects = ray.intersectObject( intersectionPlane );
			offset.copy( intersects[ 0 ].point ).subSelf( intersectionPlane.position );

118 119 120
			document.addEventListener( 'mousemove', onMouseMove, false );
			document.addEventListener( 'mouseup', onMouseUp, false );

M
Mr.doob 已提交
121
		} else {
122

M
Mr.doob 已提交
123
			controls.enabled = true;
124

M
Mr.doob 已提交
125
		}
126

127
	};
128

129
	var onMouseMove = function ( event ) {
130

M
Mr.doob 已提交
131 132 133 134 135 136 137 138 139
		var vector = new THREE.Vector3(
			( ( event.clientX - container.dom.offsetLeft ) / container.dom.offsetWidth ) * 2 - 1,
			- ( ( event.clientY - container.dom.offsetTop ) / container.dom.offsetHeight ) * 2 + 1,
			0.5
		);

		projector.unprojectVector( vector, camera );

		ray.set( camera.position, vector.subSelf( camera.position ).normalize() );
140

141
		var intersects = ray.intersectObject( intersectionPlane );
142

143
		if ( intersects.length > 0 ) {
144

145
			picked.position.copy( intersects[ 0 ].point.subSelf( offset ) );
M
Mr.doob 已提交
146

147
			signals.objectChanged.dispatch( picked );
M
Mr.doob 已提交
148

149
			render();
M
Mr.doob 已提交
150 151

		}
152

153
	};
154

155
	var onMouseUp = function ( event ) {
156

157 158
		document.removeEventListener( 'mousemove', onMouseMove );
		document.removeEventListener( 'mouseup', onMouseUp );
159

160
	};
161

162
	var onClick = function ( event ) {
163

164 165 166 167 168
		var vector = new THREE.Vector3(
			( ( event.clientX - container.dom.offsetLeft ) / container.dom.offsetWidth ) * 2 - 1,
			- ( ( event.clientY - container.dom.offsetTop ) / container.dom.offsetHeight ) * 2 + 1,
			0.5
		);
M
Mr.doob 已提交
169

170 171
		projector.unprojectVector( vector, camera );

M
Mr.doob 已提交
172
		ray.set( camera.position, vector.subSelf( camera.position ).normalize() );
173
		var intersects = ray.intersectObjects( objects, true );
174

M
Mr.doob 已提交
175
		if ( intersects.length > 0 ) {
176

177
			selected = intersects[ 0 ].object;
178 179 180

		} else {

181
			selected = null;
182 183 184

		}

185 186
		signals.objectSelected.dispatch( selected );

187
	};
188

189 190
	container.dom.addEventListener( 'mousedown', onMouseDown, false );
	container.dom.addEventListener( 'click', onClick, false );
191

192 193 194 195 196 197 198 199 200 201 202 203 204
	// controls need to be added *after* main logic,
	// otherwise controls.enabled doesn't work.

	var controls = new THREE.TrackballControls( camera, container.dom );
	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;
	controls.addEventListener( 'change', render );

205
	// signals
206 207 208

	signals.objectAdded.add( function ( object ) {

M
Mr.doob 已提交
209
		object.traverse( function ( child ) {
210 211 212 213 214

			objects.push( child );

		} );

215 216 217
		scene.add( object );
		render();

218 219
		signals.sceneChanged.dispatch( scene );

220 221
	} );

M
Mr.doob 已提交
222 223
	signals.objectChanged.add( function ( object ) {

224 225 226 227 228 229
		if ( object instanceof THREE.Camera ) {

			object.updateProjectionMatrix();

		}

M
Mr.doob 已提交
230 231 232 233
		render();

	} );

234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
	signals.objectRemoved.add( function ( ) {

		if ( !selected ) {

			console.warn( "No object selected for delete" );
			return;

		}

		var toRemove = {};

		selected.traverse( function ( child ) {

			toRemove[ child.id ] = true;

		} );

		var newObjects = [];

		for ( var i = 0; i < objects.length; i ++ ) {

			var object = objects[ i ];

			if ( ! ( object.id in toRemove ) ) {

				newObjects.push( object );

			}

		}

		objects = newObjects;

		selectionBox.visible = false;
		selectionAxis.visible = false;

		scene.traverse( function( node ) {

			node.remove( selected );

		} );

		render();

		signals.sceneChanged.dispatch( scene );
		signals.objectSelected.dispatch( null );

	} );

283
	var selected = null;
284

285
	signals.objectSelected.add( function ( object ) {
286

287
		selectionBox.visible = false;
M
Mr.doob 已提交
288
		selectionAxis.visible = false;
289

290
		if ( object !== null && object.geometry ) {
291 292 293 294 295 296 297 298 299

			var geometry = object.geometry;

			if ( geometry.boundingBox === null ) {

				geometry.computeBoundingBox();

			}

300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
			selectionBox.geometry.vertices[ 0 ].x = geometry.boundingBox.max.x;
			selectionBox.geometry.vertices[ 0 ].y = geometry.boundingBox.max.y;
			selectionBox.geometry.vertices[ 0 ].z = geometry.boundingBox.max.z;

			selectionBox.geometry.vertices[ 1 ].x = geometry.boundingBox.max.x;
			selectionBox.geometry.vertices[ 1 ].y = geometry.boundingBox.max.y;
			selectionBox.geometry.vertices[ 1 ].z = geometry.boundingBox.min.z;

			selectionBox.geometry.vertices[ 2 ].x = geometry.boundingBox.max.x;
			selectionBox.geometry.vertices[ 2 ].y = geometry.boundingBox.min.y;
			selectionBox.geometry.vertices[ 2 ].z = geometry.boundingBox.max.z;

			selectionBox.geometry.vertices[ 3 ].x = geometry.boundingBox.max.x;
			selectionBox.geometry.vertices[ 3 ].y = geometry.boundingBox.min.y;
			selectionBox.geometry.vertices[ 3 ].z = geometry.boundingBox.min.z;

			selectionBox.geometry.vertices[ 4 ].x = geometry.boundingBox.min.x;
			selectionBox.geometry.vertices[ 4 ].y = geometry.boundingBox.max.y;
			selectionBox.geometry.vertices[ 4 ].z = geometry.boundingBox.min.z;

			selectionBox.geometry.vertices[ 5 ].x = geometry.boundingBox.min.x;
			selectionBox.geometry.vertices[ 5 ].y = geometry.boundingBox.max.y;
			selectionBox.geometry.vertices[ 5 ].z = geometry.boundingBox.max.z;

			selectionBox.geometry.vertices[ 6 ].x = geometry.boundingBox.min.x;
			selectionBox.geometry.vertices[ 6 ].y = geometry.boundingBox.min.y;
			selectionBox.geometry.vertices[ 6 ].z = geometry.boundingBox.min.z;

			selectionBox.geometry.vertices[ 7 ].x = geometry.boundingBox.min.x;
			selectionBox.geometry.vertices[ 7 ].y = geometry.boundingBox.min.y;
			selectionBox.geometry.vertices[ 7 ].z = geometry.boundingBox.max.z;

332 333
			selectionBox.geometry.computeBoundingSphere();

334 335
			selectionBox.geometry.verticesNeedUpdate = true;

M
Mr.doob 已提交
336
			selectionBox.matrixWorld = object.matrixWorld;
M
Mr.doob 已提交
337
			selectionAxis.matrixWorld = object.matrixWorld;
338 339

			selectionBox.visible = true;
M
Mr.doob 已提交
340
			selectionAxis.visible = true;
341 342 343

		}

344 345 346 347 348 349
		if ( object !== null ) {

			selected = object;

		}

350 351 352 353
		render();

	} );

M
Mr.doob 已提交
354 355 356 357 358 359
	signals.materialChanged.add( function ( material ) {

		render();

	} );

360 361 362 363 364 365 366 367 368 369 370 371 372
	signals.windowResize.add( function () {

		camera.aspect = container.dom.offsetWidth / container.dom.offsetHeight;
		camera.updateProjectionMatrix();

		renderer.setSize( container.dom.offsetWidth, container.dom.offsetHeight );

		render();

	} );

	//

373
	var renderer = new THREE.WebGLRenderer( { antialias: true, alpha: false, clearColor: 0xaaaaaa, clearAlpha: 1 } );
M
Mr.doob 已提交
374
	renderer.autoClear = false;
375
	renderer.autoUpdateScene = false;
M
Mr.doob 已提交
376 377 378 379 380 381 382 383 384 385 386 387 388 389 390
	container.dom.appendChild( renderer.domElement );

	animate();

	//

	function animate() {

		requestAnimationFrame( animate );
		controls.update();

	}

	function render() {

M
Mr.doob 已提交
391
		sceneHelpers.updateMatrixWorld();
M
Mr.doob 已提交
392
		scene.updateMatrixWorld();
393

M
Mr.doob 已提交
394
		renderer.clear();
M
Mr.doob 已提交
395
		renderer.render( scene, camera );
M
Mr.doob 已提交
396
		renderer.render( sceneHelpers, camera );
M
Mr.doob 已提交
397 398 399 400 401 402

	}

	return container;

}