webvr_paint.html 9.7 KB
Newer Older
1 2 3 4 5 6
<!DOCTYPE html>
<html lang="en">
	<head>
		<title>three.js webvr - paint</title>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
M
Mr.doob 已提交
7
		<link type="text/css" rel="stylesheet" href="main.css">
M
Mugen87 已提交
8 9
		<!-- WebXR Device API (For Chrome M76+), expires 12/04/2019 -->
		<meta http-equiv="origin-trial" content="Aq9LklhCLNUveuCr7QTpGpqwCPG817cYHdVyQuJPOZYk47iRB390lUKa5edVmgS1pZSl8HPspElEC/91Fz55dwIAAABTeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZU03NiIsImV4cGlyeSI6MTU3NTQxNzU5OX0=">
10 11 12
	</head>
	<body>

M
Mr.doob 已提交
13 14 15 16
		<div id="info">
			<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> webvr - paint
		</div>

17
		<script src="js/vr/HelioWebXRPolyfill.js"></script>
18

M
Mugen87 已提交
19
		<script type="module">
20

M
Mr.doob 已提交
21
			import * as THREE from '../build/three.module.js';
22
			import { WEBVR } from './jsm/vr/WebVR.js';
M
Mugen87 已提交
23

24 25 26 27 28 29 30
			var container;
			var camera, scene, renderer;
			var controller1, controller2;

			var line;
			var shapes = {};

M
Mr.doob 已提交
31
			var up = new THREE.Vector3( 0, 1, 0 );
32

M
Mr.doob 已提交
33 34 35 36
			var vector1 = new THREE.Vector3();
			var vector2 = new THREE.Vector3();
			var vector3 = new THREE.Vector3();
			var vector4 = new THREE.Vector3();
37 38 39 40 41 42 43 44 45 46

			init();
			initGeometry();
			animate();

			function init() {

				container = document.createElement( 'div' );
				document.body.appendChild( container );

M
Mr.doob 已提交
47 48
				scene = new THREE.Scene();
				scene.background = new THREE.Color( 0x222222 );
49

M
Mr.doob 已提交
50
				camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 50 );
51

M
Mr.doob 已提交
52 53
				var geometry = new THREE.BoxBufferGeometry( 0.5, 0.8, 0.5 );
				var material = new THREE.MeshStandardMaterial( {
54 55 56 57
					color: 0x444444,
					roughness: 1.0,
					metalness: 0.0
				} );
M
Mr.doob 已提交
58
				var table = new THREE.Mesh( geometry, material );
59 60 61 62
				table.position.y = 0.35;
				table.position.z = 0.85;
				scene.add( table );

M
Mr.doob 已提交
63 64
				var geometry = new THREE.PlaneBufferGeometry( 4, 4 );
				var material = new THREE.MeshStandardMaterial( {
65 66 67 68
					color: 0x222222,
					roughness: 1.0,
					metalness: 0.0
				} );
M
Mr.doob 已提交
69
				var floor = new THREE.Mesh( geometry, material );
70 71 72
				floor.rotation.x = - Math.PI / 2;
				scene.add( floor );

M
Mr.doob 已提交
73
				var grid = new THREE.GridHelper( 10, 20, 0x111111, 0x111111 );
M
Mr.doob 已提交
74 75
				grid.material.depthTest = false; // avoid z-fighting
				scene.add( grid );
76

M
Mr.doob 已提交
77
				scene.add( new THREE.HemisphereLight( 0x888877, 0x777788 ) );
78

M
Mr.doob 已提交
79
				var light = new THREE.DirectionalLight( 0xffffff, 0.5 );
M
Mr.doob 已提交
80
				light.position.set( 0, 4, 0 );
81 82 83 84
				scene.add( light );

				//

M
Mr.doob 已提交
85
				renderer = new THREE.WebGLRenderer( { antialias: true } );
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
				renderer.setPixelRatio( window.devicePixelRatio );
				renderer.setSize( window.innerWidth, window.innerHeight );
				renderer.gammaInput = true;
				renderer.gammaOutput = true;
				renderer.vr.enabled = true;
				container.appendChild( renderer.domElement );

				document.body.appendChild( WEBVR.createButton( renderer ) );

				// controllers

				function onSelectStart() {

					this.userData.isSelecting = true;

				}

				function onSelectEnd() {

					this.userData.isSelecting = false;

				}

				controller1 = renderer.vr.getController( 0 );
				controller1.addEventListener( 'selectstart', onSelectStart );
				controller1.addEventListener( 'selectend', onSelectEnd );
M
Mr.doob 已提交
112 113
				controller1.userData.points = [ new THREE.Vector3(), new THREE.Vector3() ];
				controller1.userData.matrices = [ new THREE.Matrix4(), new THREE.Matrix4() ];
114 115 116 117 118
				scene.add( controller1 );

				controller2 = renderer.vr.getController( 1 );
				controller2.addEventListener( 'selectstart', onSelectStart );
				controller2.addEventListener( 'selectend', onSelectEnd );
M
Mr.doob 已提交
119 120
				controller2.userData.points = [ new THREE.Vector3(), new THREE.Vector3() ];
				controller2.userData.matrices = [ new THREE.Matrix4(), new THREE.Matrix4() ];
121 122
				scene.add( controller2 );

M
Mr.doob 已提交
123
				//
124

M
Mr.doob 已提交
125
				var geometry = new THREE.CylinderBufferGeometry( 0.01, 0.02, 0.08, 5 );
M
Mr.doob 已提交
126
				geometry.rotateX( - Math.PI / 2 );
M
Mr.doob 已提交
127 128
				var material = new THREE.MeshStandardMaterial( { flatShading: true } );
				var mesh = new THREE.Mesh( geometry, material );
129

M
Mr.doob 已提交
130
				var pivot = new THREE.Mesh( new THREE.IcosahedronBufferGeometry( 0.01, 2 ) );
M
Mr.doob 已提交
131 132 133
				pivot.name = 'pivot';
				pivot.position.z = - 0.05;
				mesh.add( pivot );
134

M
Mr.doob 已提交
135 136
				controller1.add( mesh.clone() );
				controller2.add( mesh.clone() );
137 138 139 140 141 142 143 144 145

				//

				window.addEventListener( 'resize', onWindowResize, false );

			}

			function initGeometry() {

M
Mr.doob 已提交
146
				var geometry = new THREE.BufferGeometry();
147

M
Mr.doob 已提交
148
				var positions = new THREE.BufferAttribute( new Float32Array( 1000000 * 3 ), 3 );
149
				positions.usage = THREE.DynamicDrawUsage;
150
				geometry.setAttribute( 'position', positions );
151

M
Mr.doob 已提交
152
				var normals = new THREE.BufferAttribute( new Float32Array( 1000000 * 3 ), 3 );
153
				normals.usage = THREE.DynamicDrawUsage;
154
				geometry.setAttribute( 'normal', normals );
155

M
Mr.doob 已提交
156
				var colors = new THREE.BufferAttribute( new Float32Array( 1000000 * 3 ), 3 );
157
				colors.usage = THREE.DynamicDrawUsage;
158
				geometry.setAttribute( 'color', colors );
159 160 161

				geometry.drawRange.count = 0;

M
Mr.doob 已提交
162
				var material = new THREE.MeshStandardMaterial( {
163 164
					roughness: 0.9,
					metalness: 0.0,
M
Mr.doob 已提交
165
					vertexColors: THREE.VertexColors
166 167
				} );

M
Mr.doob 已提交
168
				line = new THREE.Mesh( geometry, material );
169 170 171 172 173
				line.frustumCulled = false;
				scene.add( line );

				// Shapes
				shapes[ 'tube' ] = getTubeShapes( 1.0 );
L
Lewy Blue 已提交
174

175 176 177 178 179 180 181 182 183 184
			}

			function getTubeShapes( size ) {

				var PI2 = Math.PI * 2;

				var sides = 10;
				var array = [];
				var radius = 0.01 * size;

L
Lewy Blue 已提交
185
				for ( var i = 0; i < sides; i ++ ) {
186 187

					var angle = ( i / sides ) * PI2;
M
Mr.doob 已提交
188
					array.push( new THREE.Vector3( Math.sin( angle ) * radius, Math.cos( angle ) * radius, 0 ) );
189 190 191 192 193

				}

				return array;

L
Lewy Blue 已提交
194
			}
195 196 197

			function stroke( controller, point1, point2, matrix1, matrix2 ) {

M
Mr.doob 已提交
198
				var color = new THREE.Color( 0xffffff );
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 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 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 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 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372
				var size = 1;

				var shapes = getTubeShapes( size );

				var geometry = line.geometry;
				var attributes = geometry.attributes;
				var count = geometry.drawRange.count;

				var positions = attributes.position.array;
				var normals = attributes.normal.array;
				var colors = attributes.color.array;

				for ( var j = 0, jl = shapes.length; j < jl; j ++ ) {

					var vertex1 = shapes[ j ];
					var vertex2 = shapes[ ( j + 1 ) % jl ];

					// positions

					vector1.copy( vertex1 );
					vector1.applyMatrix4( matrix2 );
					vector1.add( point2 );

					vector2.copy( vertex2 );
					vector2.applyMatrix4( matrix2 );
					vector2.add( point2 );

					vector3.copy( vertex2 );
					vector3.applyMatrix4( matrix1 );
					vector3.add( point1 );

					vector4.copy( vertex1 );
					vector4.applyMatrix4( matrix1 );
					vector4.add( point1 );

					vector1.toArray( positions, ( count + 0 ) * 3 );
					vector2.toArray( positions, ( count + 1 ) * 3 );
					vector4.toArray( positions, ( count + 2 ) * 3 );

					vector2.toArray( positions, ( count + 3 ) * 3 );
					vector3.toArray( positions, ( count + 4 ) * 3 );
					vector4.toArray( positions, ( count + 5 ) * 3 );

					// normals

					vector1.copy( vertex1 );
					vector1.applyMatrix4( matrix2 );
					vector1.normalize();

					vector2.copy( vertex2 );
					vector2.applyMatrix4( matrix2 );
					vector2.normalize();

					vector3.copy( vertex2 );
					vector3.applyMatrix4( matrix1 );
					vector3.normalize();

					vector4.copy( vertex1 );
					vector4.applyMatrix4( matrix1 );
					vector4.normalize();

					vector1.toArray( normals, ( count + 0 ) * 3 );
					vector2.toArray( normals, ( count + 1 ) * 3 );
					vector4.toArray( normals, ( count + 2 ) * 3 );

					vector2.toArray( normals, ( count + 3 ) * 3 );
					vector3.toArray( normals, ( count + 4 ) * 3 );
					vector4.toArray( normals, ( count + 5 ) * 3 );

					// colors

					color.toArray( colors, ( count + 0 ) * 3 );
					color.toArray( colors, ( count + 1 ) * 3 );
					color.toArray( colors, ( count + 2 ) * 3 );

					color.toArray( colors, ( count + 3 ) * 3 );
					color.toArray( colors, ( count + 4 ) * 3 );
					color.toArray( colors, ( count + 5 ) * 3 );

					count += 6;

				}

				geometry.drawRange.count = count;

			}

			function updateGeometry( start, end ) {

				if ( start === end ) return;

				var offset = start * 3;
				var count = ( end - start ) * 3;

				var geometry = line.geometry;
				var attributes = geometry.attributes;

				attributes.position.updateRange.offset = offset;
				attributes.position.updateRange.count = count;
				attributes.position.needsUpdate = true;

				attributes.normal.updateRange.offset = offset;
				attributes.normal.updateRange.count = count;
				attributes.normal.needsUpdate = true;

				attributes.color.updateRange.offset = offset;
				attributes.color.updateRange.count = count;
				attributes.color.needsUpdate = true;

			}

			function onWindowResize() {

				camera.aspect = window.innerWidth / window.innerHeight;
				camera.updateProjectionMatrix();

				renderer.setSize( window.innerWidth, window.innerHeight );

			}

			//

			function handleController( controller ) {

				var pivot = controller.getObjectByName( 'pivot' );

				if ( pivot ) {

					var matrix = pivot.matrixWorld;

					var point1 = controller.userData.points[ 0 ];
					var point2 = controller.userData.points[ 1 ];

					var matrix1 = controller.userData.matrices[ 0 ];
					var matrix2 = controller.userData.matrices[ 1 ];

					point1.setFromMatrixPosition( matrix );
					matrix1.lookAt( point2, point1, up );

					if ( controller.userData.isSelecting === true ) {

						stroke( controller, point1, point2, matrix1, matrix2 );

					}

					point2.copy( point1 );
					matrix2.copy( matrix1 );

				}

			}

			function animate() {

				renderer.setAnimationLoop( render );

			}

			function render() {

				var count = line.geometry.drawRange.count;

				handleController( controller1 );
				handleController( controller2 );

				updateGeometry( count, line.geometry.drawRange.count );

				renderer.render( scene, camera );

			}

		</script>
	</body>
</html>