ThreeJs: webgl_geometry_shapes.html

<!DOCTYPE html>
<html lang="en">
	<head>
	<title>three.js webgl - geometry - shapes</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 src="js/three.js"></script>
	<script src="js/libs/stats.min.js"></script>

	<script>

		var container, stats;

		var camera, scene, renderer;

		var group;

		var targetRotation = 0;
		var targetRotationOnMouseDown = 0;

		var mouseX = 0;
		var mouseXOnMouseDown = 0;

		var windowHalfX = window.innerWidth / 2;

		init();
		animate();

		function init() {

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

		var info = document.createElement( 'div' );
		info.style.position = 'absolute';
		info.style.top = '10px';
		info.style.width = '100%';
		info.style.textAlign = 'center';
		info.innerHTML = 'Simple procedurally-generated shapes<br/>Drag to spin';
		container.appendChild( info );

		scene = new THREE.Scene();
		scene.background = new THREE.Color( 0xf0f0f0 );
		
		camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 1000 );
		camera.position.set( 0, 150, 500 );
		scene.add( camera );

		var light = new THREE.PointLight( 0xffffff, 0.8 );
		camera.add( light );

		group = new THREE.Group();
		group.position.y = 50;
		scene.add( group );

		var loader = new THREE.TextureLoader();
		var texture = loader.load( "textures/UV_Grid_Sm.jpg" );

		// it's necessary to apply these settings in order to correctly display the texture on a shape geometry

		texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
		texture.repeat.set( 0.008, 0.008 );

		function addShape( shape, extrudeSettings, color, position, rotation, s ,transparent) {

			// flat shape with texture
			// note: default UVs generated by ShapeBufferGeometry are simply the x- and y-coordinates of the vertices

			var geometry = new THREE.ShapeBufferGeometry( shape );
/*
			var mesh = new THREE.Mesh( geometry, new THREE.MeshPhongMaterial( { side: THREE.DoubleSide, map: texture } ) );
			mesh.position.set( position.x, position.y, position.z - 175 );
			mesh.rotation.set( rotation.x, rotation.y, rotation.z );
			mesh.scale.set( s, s, s );
			group.add( mesh );

			// flat shape

			var geometry = new THREE.ShapeBufferGeometry( shape );

			var mesh = new THREE.Mesh( geometry, new THREE.MeshPhongMaterial( { color: color, side: THREE.DoubleSide } ) );
			mesh.position.set(  position.x, position.y, position.z - 125 );
			mesh.rotation.set( rotation.x, rotation.y, rotation.z );
			mesh.scale.set( s, s, s );
			group.add( mesh );
*/
			// extruded shape

			var geometry = new THREE.ExtrudeBufferGeometry( shape, extrudeSettings );
			var material = new THREE.MeshPhongMaterial( { color: color } )
			material.transparent = transparent === true ? true : false;
			if (material.transparent) {
				/*
				 * opacity和blending都可以設置成透明度。
				 * 
				 * opacity:  自己調整0~1之間的值, 比起blending自由
				 * blending:固定的幾個值 three.js中已經定義好
				 *           "NoBlending", "NormalBlending", "AdditiveBlending", 
				 *           "SubtractiveBlending", "MultiplyBlending", "CustomBlending"
				 */
				material.opacity = 0.8
				// material.blending = THREE[ 'AdditiveBlending' ];
			}
			var mesh = new THREE.Mesh( geometry,  material);
			
			mesh.position.set( position.x, position.y, position.z - 75 );
			mesh.rotation.set( rotation.x, rotation.y, rotation.z );
			mesh.scale.set( s, s, s );
			group.add( mesh );

			//addLineShape( shape, color, x, y, z, rx, ry, rz, s );

		}

		function addLineShape( shape, color, x, y, z, rx, ry, rz, s ) {

			// lines

			shape.autoClose = true;

			var points = shape.getPoints();
			var spacedPoints = shape.getSpacedPoints( 50 );

			var geometryPoints = new THREE.BufferGeometry().setFromPoints( points );
			var geometrySpacedPoints = new THREE.BufferGeometry().setFromPoints( spacedPoints );

			// solid line

			var line = new THREE.Line( geometryPoints, new THREE.LineBasicMaterial( { color: color } ) );
			line.position.set( x, y, z - 25 );
			line.rotation.set( rx, ry, rz );
			line.scale.set( s, s, s );
			group.add( line );

			// line from equidistance sampled points

			var line = new THREE.Line( geometrySpacedPoints, new THREE.LineBasicMaterial( { color: color } ) );
			line.position.set( x, y, z + 25 );
			line.rotation.set( rx, ry, rz );
			line.scale.set( s, s, s );
			group.add( line );

			// vertices from real points

			var particles = new THREE.Points( geometryPoints, new THREE.PointsMaterial( { color: color, size: 4 } ) );
			particles.position.set( x, y, z + 75 );
			particles.rotation.set( rx, ry, rz );
			particles.scale.set( s, s, s );
			group.add( particles );

			// equidistance sampled points

			var particles = new THREE.Points( geometrySpacedPoints, new THREE.PointsMaterial( { color: color, size: 4 } ) );
			particles.position.set( x, y, z + 125 );
			particles.rotation.set( rx, ry, rz );
			particles.scale.set( s, s, s );
			group.add( particles );

		}
		var x = 0, y = 0;
		var extrudeSettings = { depth: 8, bevelEnabled: true, bevelSegments: 2, steps: 2, bevelSize: 1, bevelThickness: 1 };
		
		function showCaliforniaShape() {
			// California

			var californiaPts = [];

			californiaPts.push( new THREE.Vector2( 610, 320 ) );
			californiaPts.push( new THREE.Vector2( 450, 300 ) );
			californiaPts.push( new THREE.Vector2( 392, 392 ) );
			californiaPts.push( new THREE.Vector2( 266, 438 ) );
			californiaPts.push( new THREE.Vector2( 190, 570 ) );
			californiaPts.push( new THREE.Vector2( 190, 600 ) );
			californiaPts.push( new THREE.Vector2( 160, 620 ) );
			californiaPts.push( new THREE.Vector2( 160, 650 ) );
			californiaPts.push( new THREE.Vector2( 180, 640 ) );
			californiaPts.push( new THREE.Vector2( 165, 680 ) );
			californiaPts.push( new THREE.Vector2( 150, 670 ) );
			californiaPts.push( new THREE.Vector2( 90, 737 ) );
			californiaPts.push( new THREE.Vector2( 80, 795 ) );
			californiaPts.push( new THREE.Vector2( 50, 835 ) );
			californiaPts.push( new THREE.Vector2( 64, 870 ) );
			californiaPts.push( new THREE.Vector2( 60, 945 ) );
			californiaPts.push( new THREE.Vector2( 300, 945 ) );
			californiaPts.push( new THREE.Vector2( 300, 743 ) );
			californiaPts.push( new THREE.Vector2( 600, 473 ) );
			californiaPts.push( new THREE.Vector2( 626, 425 ) );
			californiaPts.push( new THREE.Vector2( 600, 370 ) );
			californiaPts.push( new THREE.Vector2( 610, 320 ) );

			for ( var i = 0; i < californiaPts.length; i ++ ) californiaPts[ i ].multiplyScalar( 0.25 );

			var californiaShape = new THREE.Shape( californiaPts );
			var position = {x:-300,y: - 100,z:0}
			var rotation = {x:0,y:0,z:0};
			addShape( californiaShape, extrudeSettings, 0xf08000, position, rotation, 1 );
		}
		function shwoTriangleShape() {
			// Triangle

			var triangleShape = new THREE.Shape();
			triangleShape.moveTo( 80, 20 );
			triangleShape.lineTo( 40, 80 );
			triangleShape.lineTo( 120, 80 );
			triangleShape.lineTo( 80, 20 ); // close path
			
			var position = {x:-180,y: 0,z:0}
			var rotation = {x:0,y:0,z:0};
			addShape( triangleShape, extrudeSettings, 0x8080f0, position, rotation, 1 );
		}
		
		function showArcShape() {
			// Arc circle
			var arcShape = new THREE.Shape();
			arcShape.moveTo( 50, 10 );
			arcShape.absarc( 10, 10, 40, 0, Math.PI * 2, false );

			var holePath = new THREE.Path();
			holePath.moveTo( 20, 10 );
			holePath.absarc( 10, 10, 10, 0, Math.PI * 2, true );
			arcShape.holes.push( holePath );
			
			var position = {x:150,y: 0,z:0}
			var rotation = {x:0,y:0,z:0}
			addShape( arcShape, extrudeSettings, 0x804000, position, rotation, 1 );
			addLineShape( arcShape.holes[ 0 ], 0x804000, 150, 0, 0, 0, 0, 0, 1 );
		}
		/**
		 * 圓角方形
		 */
		function showRoundedRectShape() {
			// Rounded rectangle
			var roundedRectShape = new THREE.Shape();

			( function roundedRect( ctx, x, y, width, height, radius ) {

			ctx.moveTo( x, y + radius );
			ctx.lineTo( x, y + height - radius );
			ctx.quadraticCurveTo( x, y + height, x + radius, y + height );
			ctx.lineTo( x + width - radius, y + height );
			ctx.quadraticCurveTo( x + width, y + height, x + width, y + height - radius );
			ctx.lineTo( x + width, y + radius );
			ctx.quadraticCurveTo( x + width, y, x + width - radius, y );
			ctx.lineTo( x + radius, y );
			ctx.quadraticCurveTo( x, y, x, y + radius );

			} )( roundedRectShape, 0, 0, 50, 50, 20 );
			
			var position = {x:-150,y: 150,z:0}
			var rotation = {x:0,y:0,z:0}
			addShape( roundedRectShape, extrudeSettings, 0x008000, position, rotation, 1 );
		}
		
		function showHeartShape() {
			var heartShape = new THREE.Shape(); // From http://blog.burlock.org/html5/130-paths

			heartShape.moveTo( x + 25, y + 25 );
			heartShape.bezierCurveTo( x + 25, y + 25, x + 20, y, x, y );
			heartShape.bezierCurveTo( x - 30, y, x - 30, y + 35, x - 30, y + 35 );
			heartShape.bezierCurveTo( x - 30, y + 55, x - 10, y + 77, x + 25, y + 95 );
			heartShape.bezierCurveTo( x + 60, y + 77, x + 80, y + 55, x + 80, y + 35 );
			heartShape.bezierCurveTo( x + 80, y + 35, x + 80, y, x + 50, y );
			heartShape.bezierCurveTo( x + 35, y, x + 25, y + 25, x + 25, y + 25 );
			
			var position = {x:60,y: 100,z:0}
			var rotation = {x:0,y:0,z: Math.PI}
			addShape( heartShape, extrudeSettings, 0xf00000, position, rotation, 1 );

			
		}
		function showSquareShape() {
			// Square
			var sqLength = 80;

			var squareShape = new THREE.Shape();
			squareShape.moveTo( 0, 0 );
			squareShape.lineTo( 0, sqLength );
			squareShape.lineTo( sqLength, sqLength );
			squareShape.lineTo( sqLength, 0 );
			squareShape.lineTo( 0, 0 );
			
			var position = {x:150,y: 100,z:0}
			var rotation = {x:0,y:0,z:0}
			
			addShape( squareShape, extrudeSettings, 0x0040f0, position, rotation, 1 );
		}
		/*
		 * 橢圓桌
		 */
		function showTrackShape() {
			// Track

			var trackShape = new THREE.Shape();
			const start_X = 50;
			const start_Y = 20;
			const end_X = 200;
			const end_Y = 100;
			const radius = Math.abs(start_X - end_X) / 2; // 半徑
			trackShape.moveTo( start_X, start_Y );	// 開始點
			trackShape.lineTo( start_X, end_Y );	// 畫線
			/*
			 * absarc的解釋
			 * 參考:https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/arc
			 * x:圓弧中心(圓心)的 x 軸座標。
			 * y:圓弧中心(圓心)的 y 軸座標。
			 * radius:圓弧的半徑。
			 * startAngle:圓弧的起始點, x軸方向開始計算,單位以弧度表示。
			 * endAngle:  圓弧的終點, 單位以弧度表示。
			 * anticlockwise:可選,可選的Boolean值 ,如果爲 true,逆時針繪製圓弧,反之,順時針繪製。 
			 */
			trackShape.absarc( Math.abs(start_X - end_X) / 2 + start_X, end_Y, radius, Math.PI, 0, true ); // 弧線,並且第三個點
			trackShape.lineTo( end_X, start_Y );	// 結束點
			trackShape.absarc( Math.abs(start_X - end_X) / 2 + start_X, start_Y, radius, 2 * Math.PI, Math.PI, true ); // 弧線,並且回到開始點
			
			var position = {x:0,y: 0,z:-100}
			var rotation = {x:0,y:0,z:0}
			// var rotation = {x:Math.PI/2,y:0,z:0}
			addShape( trackShape, extrudeSettings, 0x008080, position, rotation, 1 , true);

		}
		function shwoCircleShape() {
			// Circle

			var circleRadius = 40;
			var circleShape = new THREE.Shape();
			circleShape.moveTo( 0, circleRadius );
			circleShape.quadraticCurveTo( circleRadius, circleRadius, circleRadius, 0 );
			circleShape.quadraticCurveTo( circleRadius, - circleRadius, 0, - circleRadius );
			circleShape.quadraticCurveTo( - circleRadius, - circleRadius, - circleRadius, 0 );
			circleShape.quadraticCurveTo( - circleRadius, circleRadius, 0, circleRadius );
			
			var position = {x:120,y: 250,z:0}
			var rotation = {x:0,y:0,z:0}
			addShape( circleShape, extrudeSettings, 0x00f000, position, rotation, 1 );
		}

		
		function showFishShape () {
			// Fish

			var x = y = 0;

			var fishShape = new THREE.Shape();

			fishShape.moveTo( x, y );
			fishShape.quadraticCurveTo( x + 50, y - 80, x + 90, y - 10 );
			fishShape.quadraticCurveTo( x + 100, y - 10, x + 115, y - 40 );
			fishShape.quadraticCurveTo( x + 115, y, x + 115, y + 40 );
			fishShape.quadraticCurveTo( x + 100, y + 10, x + 90, y + 10 );
			fishShape.quadraticCurveTo( x + 50, y + 80, x, y );
			
			var position = {x:- 60,y: 200,z:0}
			var rotation = {x:0,y:0,z:0}
			addShape( fishShape, extrudeSettings, 0x404040, position, rotation, 1 );
		}
		
		function showSmileyShape() {
			// Smiley
			var smileyShape = new THREE.Shape();
			smileyShape.moveTo( 80, 40 );
			smileyShape.absarc( 40, 40, 40, 0, Math.PI * 2, false );

			var smileyEye1Path = new THREE.Path();
			smileyEye1Path.moveTo( 35, 20 );
			smileyEye1Path.absellipse( 25, 20, 10, 10, 0, Math.PI * 2, true );

			smileyShape.holes.push( smileyEye1Path );

			var smileyEye2Path = new THREE.Path();
			smileyEye2Path.moveTo( 65, 20 );
			smileyEye2Path.absarc( 55, 20, 10, 0, Math.PI * 2, true );
			smileyShape.holes.push( smileyEye2Path );

			var smileyMouthPath = new THREE.Path();
			smileyMouthPath.moveTo( 20, 40 );
			smileyMouthPath.quadraticCurveTo( 40, 60, 60, 40 );
			smileyMouthPath.bezierCurveTo( 70, 45, 70, 50, 60, 60 );
			smileyMouthPath.quadraticCurveTo( 40, 80, 20, 60 );
			smileyMouthPath.quadraticCurveTo( 5, 50, 20, 40 );

			smileyShape.holes.push( smileyMouthPath );
			
			var position = {x:- 200,y: 250,z:0}
			var rotation = {x:0,y:0,z:Math.PI}
			addShape( smileyShape, extrudeSettings, 0xf000f0, position, rotation, 1 );
			for ( var i = 0; i < smileyShape.holes.length; i += 1 ) {

			addLineShape( smileyShape.holes[ i ], 0xf000f0, - 200, 250, 0, 0, 0, Math.PI, 1 );

			}
		}
		function showSplineShape() {
			// Spline shape
			var splinepts = [];
			splinepts.push( new THREE.Vector2( 70, 20 ) );
			splinepts.push( new THREE.Vector2( 80, 90 ) );
			splinepts.push( new THREE.Vector2( - 30, 70 ) );
			splinepts.push( new THREE.Vector2( 0, 0 ) );

			var splineShape = new THREE.Shape();
			splineShape.moveTo( 0, 0 );
			splineShape.splineThru( splinepts );
			var position = {x:- 50,y:- 100,z:0}
			var rotation = {x:0,y:0,z:0}
			addShape( splineShape, extrudeSettings, 0x808080, position, rotation, 1 );
		}
		
		
		showCaliforniaShape() // 多邊形
		showRoundedRectShape()// 圓角方形
		shwoTriangleShape() // 三角形
		showArcShape()    // 圓
		showHeartShape()  // 心
		showSquareShape() // 正方形
		showTrackShape()  // 橢圓
		shwoCircleShape() // 圓
		showFishShape()   // 魚
		showSmileyShape() // 臉
		showSplineShape() // 多邊形
		
		
		//

		renderer = new THREE.WebGLRenderer( { antialias: true } );
		renderer.setPixelRatio( window.devicePixelRatio );
		renderer.setSize( window.innerWidth, window.innerHeight );
		container.appendChild( renderer.domElement );

		stats = new Stats();
		container.appendChild( stats.dom );

		document.addEventListener( 'mousedown', onDocumentMouseDown, false );
		document.addEventListener( 'touchstart', onDocumentTouchStart, false );
		document.addEventListener( 'touchmove', onDocumentTouchMove, false );

		//

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

		}
		
		function onWindowResize() {

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

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

		}

		//

		function onDocumentMouseDown( event ) {

		event.preventDefault();

		document.addEventListener( 'mousemove', onDocumentMouseMove, false );
		document.addEventListener( 'mouseup', onDocumentMouseUp, false );
		document.addEventListener( 'mouseout', onDocumentMouseOut, false );

		mouseXOnMouseDown = event.clientX - windowHalfX;
		targetRotationOnMouseDown = targetRotation;

		}

		function onDocumentMouseMove( event ) {

		mouseX = event.clientX - windowHalfX;

		targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.02;

		}

		function onDocumentMouseUp() {

		document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
		document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
		document.removeEventListener( 'mouseout', onDocumentMouseOut, false );

		}

		function onDocumentMouseOut() {

		document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
		document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
		document.removeEventListener( 'mouseout', onDocumentMouseOut, false );

		}

		function onDocumentTouchStart( event ) {

		if ( event.touches.length == 1 ) {

			event.preventDefault();

			mouseXOnMouseDown = event.touches[ 0 ].pageX - windowHalfX;
			targetRotationOnMouseDown = targetRotation;

		}

		}

		function onDocumentTouchMove( event ) {

		if ( event.touches.length == 1 ) {

			event.preventDefault();

			mouseX = event.touches[ 0 ].pageX - windowHalfX;
			targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.05;

		}

		}

		//

		function animate() {

		requestAnimationFrame( animate );

		render();
		stats.update();

		}

		function render() {

		group.rotation.y += ( targetRotation - group.rotation.y ) * 0.05;
		renderer.render( scene, camera );

		}

	</script>

	</body>
</html>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章