浏览代码

Added webgl terrain example.

Mr.doob 14 年之前
父节点
当前提交
2dcbde4d69
共有 4 个文件被更改,包括 337 次插入108 次删除
  1. 2 0
      README.md
  2. 40 37
      examples/geometry_minecraft.html
  3. 33 71
      examples/geometry_terrain.html
  4. 262 0
      examples/geometry_terrain_gl.html

+ 2 - 0
README.md

@@ -35,6 +35,7 @@ More? irc.freenode.net #three.js
 
 #### WebGL ####
 
+[![geometry_terrain_gl](http://mrdoob.github.com/three.js/assets/examples/30_geometry_terrain_gl.png)](http://mrdoob.github.com/three.js/examples/geometry_terrain_gl.html)
 [![geometry_minecraft](http://mrdoob.github.com/three.js/assets/examples/29_geometry_minecraft.png)](http://mrdoob.github.com/three.js/examples/geometry_minecraft.html)
 [![materials_shader_fresnel](http://mrdoob.github.com/three.js/assets/examples/28_materials_shaders_fresnel.png)](http://mrdoob.github.com/three.js/examples/materials_shaders_fresnel.html)
 [![materials_cars](http://mrdoob.github.com/three.js/assets/examples/25_materials_cars.png)](http://mrdoob.github.com/three.js/examples/materials_cars.html)
@@ -50,6 +51,7 @@ More? irc.freenode.net #three.js
 
 ### Featured projects ###
 
+[![Sculpt](http://mrdoob.github.com/three.js/assets/projects/11_sculpt.png)](http://antimatter15.com/wp/2010/11/digital-sculpting-with-three-js/)
 [![Voxels](http://mrdoob.github.com/three.js/assets/projects/10_voxels.png)](http://mrdoob.com/projects/voxels/)
 [![The Wilderness Downtown](http://mrdoob.github.com/three.js/assets/projects/09_arcadefire.png)](http://thewildernessdowntown.com/)
 [![CloudSCAD](http://mrdoob.github.com/three.js/assets/projects/08_cloudscad.png)](http://cloudscad.com/stl_viewer/)

+ 40 - 37
examples/geometry_minecraft.html

@@ -31,7 +31,7 @@
 	<body>
 
 		<div id="container"><br /><br /><br /><br /><br />Generating world...</div> 
-		<div id="info"><a href="http://github.com/mrdoob/three.js" target="_blank">three.js</a> - <a href="http://www.minecraft.net/" target="_blank">minecraft</a> demo. featuring <a href="http://painterlypack.net/" target="_blank">painterly pack</a><br />(camera move: WASD/↑←↓→)</div> 
+		<div id="info"><a href="http://github.com/mrdoob/three.js" target="_blank">three.js</a> - <a href="http://www.minecraft.net/" target="_blank">minecraft</a> demo. featuring <a href="http://painterlypack.net/" target="_blank">painterly pack</a><br />(right click: forward, left click: backward)</div> 
 
 		<script type="text/javascript" src="js/Stats.js"></script>
 		<script type="text/javascript" src="js/ImprovedNoise.js"></script>
@@ -56,8 +56,7 @@
 			lat = 0, lon = 0, phy = 0, theta = 0;
 
 			var direction = new THREE.Vector3(),
-			moveForward = false, moveBackwards = false,
-			moveLeft = false, moveRight = false;
+			moveForward = false, moveBackwards = false;
 
 			var windowHalfX = window.innerWidth / 2;
 			var windowHalfY = window.innerHeight / 2;
@@ -115,12 +114,12 @@
 				var ambientLight = new THREE.AmbientLight( 0xcccccc );
 				scene.addLight( ambientLight );
 
-				var pointLight = new THREE.DirectionalLight( 0xffffff, 1.5 );
-				pointLight.position.x = 1;
-				pointLight.position.y = 1;
-				pointLight.position.z = 0.5;
-				pointLight.position.normalize;
-				scene.addLight( pointLight );
+				var directionalLight = new THREE.DirectionalLight( 0xffffff, 1.5 );
+				directionalLight.position.x = 1;
+				directionalLight.position.y = 1;
+				directionalLight.position.z = 0.5;
+				directionalLight.position.normalize();
+				scene.addLight( directionalLight );
 
 				renderer = new THREE.WebGLRenderer();
 				renderer.setSize( window.innerWidth, window.innerHeight );
@@ -134,7 +133,11 @@
 				stats.domElement.style.top = '0px';
 				container.appendChild( stats.domElement );
 
+				document.addEventListener( 'mousedown', onDocumentMouseDown, false );
+				document.addEventListener( 'mouseup', onDocumentMouseUp, false );
 				document.addEventListener( 'mousemove', onDocumentMouseMove, false );
+				document.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
+
 				document.addEventListener( 'keydown', onDocumentKeyDown, false );
 				document.addEventListener( 'keyup', onDocumentKeyUp, false );
 
@@ -181,6 +184,34 @@
 
 			}
 
+			function onDocumentMouseDown( event ) {
+
+				event.preventDefault();
+				event.stopPropagation();
+
+				switch ( event.button ) {
+
+					case 0: moveForward = true; break;
+					case 2: moveBackwards = true; break;
+
+				}
+
+			}
+
+			function onDocumentMouseUp( event ) {
+
+				event.preventDefault();
+				event.stopPropagation();
+
+				switch ( event.button ) {
+
+					case 0: moveForward = false; break;
+					case 2: moveBackwards = false; break;
+
+				}
+
+			}
+
 			function onDocumentMouseMove(event) {
 
 				mouseX = event.clientX - windowHalfX;
@@ -189,20 +220,14 @@
 			}
 
 			function onDocumentKeyDown( event ) {
-				
-				// console.log( event.keyCode );
 
 				switch( event.keyCode ) {
 
 					case 38: /*↑*/ moveForward = true; break;
 					case 40: /*↓*/ moveBackwards = true; break;
-					case 37: /*←*/ moveLeft = true; break;
-					case 39: /*→*/ moveRight = true; break;
 
 					case 87: /*W*/ moveForward = true; break;
 					case 83: /*S*/ moveBackwards = true; break;
-					case 65: /*A*/ moveLeft = true; break;
-					case 68: /*D*/ moveRight = true; break;
 
 				}
 
@@ -214,13 +239,9 @@
 
 					case 38: /*↑*/ moveForward = false; break;
 					case 40: /*↓*/ moveBackwards = false; break;
-					case 37: /*←*/ moveLeft = false; break;
-					case 39: /*→*/ moveRight = false; break;
 
 					case 87: /*W*/ moveForward = false; break;
 					case 83: /*S*/ moveBackwards = false; break;
-					case 65: /*A*/ moveLeft = false; break;
-					case 68: /*D*/ moveRight = false; break;
 
 				}
 
@@ -244,24 +265,6 @@
 
 				}
 
-				if ( moveLeft ) {
-
-					direction.copy( camera.target.position ).subSelf( camera.position ).normalize().multiplyScalar( - 15 );
-					direction.cross( direction.clone(), new THREE.Vector3( 0, 1, 0 ) );
-					camera.position.addSelf( direction );
-					camera.target.position.addSelf( direction );
-
-				}
-
-				if ( moveRight ) {
-
-					direction.copy( camera.target.position ).subSelf( camera.position ).normalize().multiplyScalar( 15 );
-					direction.cross( direction.clone(), new THREE.Vector3( 0, 1, 0 ) );
-					camera.position.addSelf( direction );
-					camera.target.position.addSelf( direction );
-
-				};
-
 				lon += mouseX * 0.005;
 				lat -= mouseY * 0.005;
 

+ 33 - 71
examples/geometry_terrain.html

@@ -67,28 +67,16 @@
 
 				scene = new THREE.Scene();
 
-				var heightMap = height( 1024, 1024 );
+				var data = generateHeight( 1024, 1024 );
+				var material = new THREE.MeshBasicMaterial( { map: new THREE.Texture( generateTexture( data, 1024, 1024 ) ) } );
 
-				var texture = new THREE.Texture( shadow( heightMap ) );
-				texture.image.loaded = true;
+				var quality = 16, step = 1024 / quality;
+				var plane = new Plane( 2000, 2000, quality - 1, quality - 1 );
 
-				var material = new THREE.MeshBasicMaterial( { map: texture } );
+				for ( var i = 0, l = plane.vertices.length; i < l; i ++ ) {
 
-				var quality = 20;
-				var quality1 = quality + 1;
-
-				var plane = new Plane( 2000, 2000, quality, quality );
-
-				var data = heightMap.getContext( '2d' ).getImageData( 0, 0, heightMap.width, heightMap.height ).data;
-				var pixelsPerTriangle = Math.floor( heightMap.width / quality );
-
-				for ( var y = 0; y < quality1; y++ ) {
-
-					for (var x = 0; x < quality1; x++ ) {
-
-						plane.vertices[x + y * quality1].position.z = data[((x * pixelsPerTriangle) + (y * pixelsPerTriangle) * heightMap.width) * 4] * 2 - 128;
-
-					}
+					var x = i % quality, y = ~~ ( i / quality );
+					plane.vertices[ i ].position.z = data[ ( x * step ) + ( y * step ) * 1024 ] * 2 - 128;
 
 				}
 
@@ -98,7 +86,7 @@
 				mesh = new THREE.Mesh( plane, material );
 				mesh.rotation.x = -90 * Math.PI / 180;
 				mesh.overdraw = true;
-				scene.addObject(mesh);
+				scene.addObject( mesh );
 
 				renderer = new THREE.CanvasRenderer();
 				renderer.setSize( window.innerWidth, window.innerHeight );
@@ -133,60 +121,39 @@
 
 			}
 
-			function height( width, height ) {
+			function generateHeight( width, height ) {
 
-				var canvas, context, image, data;
-
-				canvas = document.createElement( 'canvas' );
-				canvas.width = width;
-				canvas.height = height;
-
-				context = canvas.getContext( '2d' );
-				context.fillStyle = '#000';
-				context.fillRect( 0, 0, width, height );
+				var data = Float32Array ? new Float32Array() : [], perlin = new ImprovedNoise(),
+				size = width * height, quality = 2, z = Math.random() * 100;
 
-				image = context.getImageData( 0, 0, width, height );
-				data = image.data;
+				for ( var i = 0; i < size; i ++ ) {
 
-				var perlin = new ImprovedNoise();
+					data[ i ] = 0
 
-				var size = width * height;
-				var quality = 2;
-				var zz = Math.random() * 100;
+				}
 
 				for ( var j = 0; j < 4; j ++ ) {
 
-					var x = 0, y = 0, yy = 0;
-
 					quality *= 4;
 
 					for ( var i = 0; i < size; i ++ ) {
 
-						data[ i * 4 ] += Math.floor( Math.abs( perlin.noise( x / quality, yy, zz ) * 0.5 ) * quality + 10 );
+						var x = i % width, y = ~~ ( i / width );
+						data[ i ] += Math.abs( perlin.noise( x / quality, y / quality, z ) * 0.5 * quality + 10 );
 
-						x++;
-
-						if (x == width)
-						{
-							x = 0;
-							y ++;
-							yy = y / quality;
-						}
 
 					}
-				}
 
-				context.putImageData( image, 0, 0 );
+				}
 
-				return canvas;
+				return data;
 
 			}
 
-			function shadow( texture ) {
+			function generateTexture( data, width, height ) {
 
-				var canvas, context, image, data, src_data,
-				index, level, diff, width = texture.width, height = texture.height,
-				vector3, sun, shade;
+				var canvas, context, image, imageData,
+				level, diff, vector3, sun, shade;
 
 				vector3 = new THREE.Vector3( 0, 0, 0 );
 
@@ -196,39 +163,34 @@
 				canvas = document.createElement( 'canvas' );
 				canvas.width = width;
 				canvas.height = height;
+				canvas.loaded = true;
 
 				context = canvas.getContext( '2d' );
 				context.fillStyle = '#000';
 				context.fillRect( 0, 0, width, height );
 
 				image = context.getImageData( 0, 0, width, height );
-				data = image.data;
-
-				src_data = texture.getContext( '2d' ).getImageData( 0, 0, width, height ).data;
-
-				for ( var y = 0; y < height; y++ ) {
+				imageData = image.data;
 
-					for ( var x = 0; x < width; x++ ) {
+				for ( var i = 0, j = 0, l = imageData.length; i < l; i += 4, j ++  ) {
 
-						index = ( x + y * width ) * 4;
+					vector3.x = data[ j - 1 ] - data[ j + 1 ];
+					vector3.y = 2;
+					vector3.z = data[ j - width ] - data[ j + width ];
+					vector3.normalize();
 
-						vector3.x = src_data[ index - 4 ] - src_data[ index + 4 ];
-						vector3.y = 2;
-						vector3.z = src_data[ index - ( width * 4 ) ] - src_data[ index + ( width * 4 ) ];
-						vector3.normalize();
+					shade = vector3.dot( sun );
 
-						shade = vector3.dot(sun);
+					imageData[ i ] = ( 96 + shade * 128 ) * ( data[ j ] * 0.007 );
+					imageData[ i + 1 ] = ( 32 + shade * 96 ) * ( data[ j ] * 0.007 );
+					imageData[ i + 2 ] = ( shade * 96 ) * ( data[ j ] * 0.007 );
 
-						data[ index ] = ( 96 + shade * 128 ) * ( src_data[ index ] * 0.007 );
-						data[ index + 1 ] = ( 32 + shade * 96 ) * ( src_data[ index ] * 0.007 );
-						data[ index + 2 ] = ( shade * 96 ) * ( src_data[ index ] * 0.007 );
-
-					}
 				}
 
 				context.putImageData( image, 0, 0 );
 
 				return canvas;
+
 			}
 
 

+ 262 - 0
examples/geometry_terrain_gl.html

@@ -0,0 +1,262 @@
+<!DOCTYPE HTML>
+<html lang="en">
+	<head>
+		<title>three.js - geometry - webgl terrain</title>
+		<meta charset="utf-8">
+		<style type="text/css">
+			body {
+				color: #61443e;
+				font-family:Monospace;
+				font-size:13px;
+				text-align:center;
+
+				background-color: #bfd1e5;
+				margin: 0px;
+				overflow: hidden;
+			}
+
+			#info {
+				position: absolute;
+				top: 0px; width: 100%;
+				padding: 5px;
+			}
+
+			a {
+
+				color: #a06851;
+			}
+
+		</style>
+	</head>
+	<body>
+
+		<div id="container"><br /><br /><br /><br /><br />Generating world...</div> 
+		<div id="info"><a href="http://github.com/mrdoob/three.js" target="_blank">three.js</a> - webgl terrain demo<br />(right click: forward, left click: backward)</div> 
+
+		<script type="text/javascript" src="js/Stats.js"></script>
+		<script type="text/javascript" src="js/ImprovedNoise.js"></script>
+
+		<script type="text/javascript" src="../build/Three.js"></script>
+		<script type="text/javascript" src="../src/extras/GeometryUtils.js"></script>
+		<script type="text/javascript" src="../src/extras/primitives/Plane.js"></script>
+
+		<script type="text/javascript">
+
+			var container, stats;
+
+			var camera, scene, renderer;
+
+			var mesh, texture;
+
+			var worldWidth = 256, worldDepth = 256,
+			worldHalfWidth = worldWidth / 2, worldHalfDepth = worldDepth / 2;
+
+			var mouseX = 0, mouseY = 0,
+			lat = 0, lon = 0, phy = 0, theta = 0;
+
+			var direction = new THREE.Vector3(),
+			moveForward = false, moveBackwards = false;
+
+			var windowHalfX = window.innerWidth / 2;
+			var windowHalfY = window.innerHeight / 2;
+
+
+			init();
+			setInterval( loop, 1000 / 60 );
+
+
+			function init() {
+
+				container = document.getElementById( 'container' );
+
+				camera = new THREE.Camera( 60, window.innerWidth / window.innerHeight, 1, 20000 );
+				camera.target.position.z = - 100;
+
+				scene = new THREE.Scene();
+
+				data = generateHeight( worldWidth, worldDepth );
+
+				camera.position.y = data[ worldHalfWidth + worldHalfDepth * worldWidth ] + 500;
+				camera.target.position.y = camera.position.y;
+
+				var geometry = new Plane( 7500, 7500, worldWidth - 1, worldDepth - 1 );
+
+				for ( var i = 0, l = geometry.vertices.length; i < l; i ++ ) {
+
+					geometry.vertices[ i ].position.z = data[ i ] * 10;
+
+				}
+
+				geometry.computeNormals();
+				geometry.computeVertexNormals();
+				geometry.sortFacesByMaterial();
+
+				texture = new THREE.Texture( generateTexture( data, worldWidth, worldDepth ), new THREE.UVMapping(), THREE.ClampToEdgeWrapping, THREE.ClampToEdgeWrapping );
+
+				mesh = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( { map: texture } ) );
+				mesh.rotation.x = - 90 * Math.PI / 180;
+				scene.addObject( mesh );
+
+				renderer = new THREE.WebGLRenderer();
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+				container.innerHTML = "";
+
+				container.appendChild( renderer.domElement );
+
+				stats = new Stats();
+				stats.domElement.style.position = 'absolute';
+				stats.domElement.style.top = '0px';
+				container.appendChild( stats.domElement );
+
+				document.addEventListener( 'mousedown', onDocumentMouseDown, false );
+				document.addEventListener( 'mouseup', onDocumentMouseUp, false );
+				document.addEventListener( 'mousemove', onDocumentMouseMove, false );
+				document.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
+
+			}
+
+			function generateHeight( width, height ) {
+
+				var data = Float32Array ? new Float32Array() : [], perlin = new ImprovedNoise(),
+				size = width * height, quality = 1, z = Math.random() * 100;
+
+				for ( var i = 0; i < size; i ++ ) {
+
+					data[ i ] = 0
+
+				}
+
+				for ( var j = 0; j < 4; j ++ ) {
+
+					for ( var i = 0; i < size; i ++ ) {
+
+						var x = i % width, y = ~~ ( i / width );
+						data[ i ] += Math.abs( perlin.noise( x / quality, y / quality, z ) * quality * 1.75 );
+
+
+					}
+
+					quality *= 5;
+
+				}
+
+				return data;
+
+			}
+
+			function generateTexture( data, width, height ) {
+
+				var canvas, context, image, imageData,
+				level, diff, vector3, sun, shade;
+
+				vector3 = new THREE.Vector3( 0, 0, 0 );
+
+				sun = new THREE.Vector3( 1, 1, 1 );
+				sun.normalize();
+
+				canvas = document.createElement( 'canvas' );
+				canvas.width = width;
+				canvas.height = height;
+				canvas.loaded = true;
+
+				context = canvas.getContext( '2d' );
+				context.fillStyle = '#000';
+				context.fillRect( 0, 0, width, height );
+
+				image = context.getImageData( 0, 0, width, height );
+				imageData = image.data;
+
+				for ( var i = 0, j = 0, l = imageData.length; i < l; i += 4, j ++  ) {
+
+					vector3.x = data[ j - 1 ] - data[ j + 1 ];
+					vector3.y = 2;
+					vector3.z = data[ j - width ] - data[ j + width ];
+					vector3.normalize();
+
+					shade = vector3.dot( sun );
+
+					imageData[ i ] = ( 96 + shade * 128 ) * ( 0.5 + data[ j ] * 0.007 );
+					imageData[ i + 1 ] = ( 32 + shade * 96 ) * ( 0.5 + data[ j ] * 0.007 );
+					imageData[ i + 2 ] = ( shade * 96 ) * ( 0.5 + data[ j ] * 0.007 );
+				}
+
+				context.putImageData( image, 0, 0 );
+
+				return canvas;
+
+			}
+
+			function onDocumentMouseDown( event ) {
+
+				event.preventDefault();
+				event.stopPropagation();
+
+				switch ( event.button ) {
+
+					case 0: moveForward = true; break;
+					case 2: moveBackwards = true; break;
+
+				}
+
+			}
+
+			function onDocumentMouseUp( event ) {
+
+				event.preventDefault();
+				event.stopPropagation();
+
+				switch ( event.button ) {
+
+					case 0: moveForward = false; break;
+					case 2: moveBackwards = false; break;
+
+				}
+
+			}
+
+			function onDocumentMouseMove(event) {
+
+				mouseX = event.clientX - windowHalfX;
+				mouseY = event.clientY - windowHalfY;
+
+			}
+
+			function loop() {
+
+				if ( moveForward ) {
+
+					direction.copy( camera.target.position ).subSelf( camera.position ).normalize().multiplyScalar( 15 );
+					camera.position.addSelf( direction );
+					camera.target.position.addSelf( direction );
+
+				}
+
+				if ( moveBackwards ) {
+
+					direction.copy( camera.target.position ).subSelf( camera.position ).normalize().multiplyScalar( - 15 );
+					camera.position.addSelf( direction );
+					camera.target.position.addSelf( direction );
+
+				}
+
+				lon += mouseX * 0.004;
+				lat -= mouseY * 0.004;
+
+				lat = Math.max( - 85, Math.min( 85, lat ) );
+				phi = ( 90 - lat ) * Math.PI / 180;
+				theta = lon * Math.PI / 180;
+
+				camera.target.position.x = 100 * Math.sin( phi ) * Math.cos( theta ) + camera.position.x;
+				camera.target.position.y = 100 * Math.cos( phi ) + camera.position.y;
+				camera.target.position.z = 100 * Math.sin( phi ) * Math.sin( theta ) + camera.position.z;
+
+				renderer.render(scene, camera);
+				stats.update();
+
+			}
+
+		</script>
+
+	</body>
+</html>