فهرست منبع

[r4317] THREE.Lines support indexed geometry

Vivien Miniussi 11 سال پیش
والد
کامیت
c89cefd422
2فایلهای تغییر یافته به همراه336 افزوده شده و 25 حذف شده
  1. 261 0
      examples/webgl_buffergeometry_lines_indexed.html
  2. 75 25
      src/renderers/WebGLRenderer.js

+ 261 - 0
examples/webgl_buffergeometry_lines_indexed.html

@@ -0,0 +1,261 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js webgl - buffergeometry</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 {
+				color: #cccccc;
+				font-family:Monospace;
+				font-size:13px;
+				text-align:center;
+
+				background-color: #000000;
+				margin: 0px;
+				overflow: hidden;
+			}
+
+			#info {
+				position: absolute;
+				top: 0px; width: 100%;
+				padding: 5px;
+			}
+
+			a {
+
+				color: #0080ff;
+			}
+
+		</style>
+	</head>
+	<body>
+
+		<div id="container"></div>
+		<div id="info"><a href="http://threejs.org" target="_blank">three.js</a> webgl - buffergeometry</div>
+
+		<script src="../build/three.min.js"></script>
+
+		<script src="js/Detector.js"></script>
+		<script src="js/libs/stats.min.js"></script>
+
+		<script>
+
+			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
+
+			var container, stats;
+
+			var camera, scene, renderer;
+
+			var mesh, parent_node;
+
+			init();
+			animate();
+
+			function init() {
+
+				container = document.getElementById( 'container' );
+
+				camera = new THREE.PerspectiveCamera( 27, window.innerWidth / window.innerHeight, 1, 10000 );
+				camera.position.z = 9000;
+
+				scene = new THREE.Scene();
+
+				var geometry = new THREE.BufferGeometry();
+				var material = new THREE.LineBasicMaterial({ vertexColors: true });
+
+				var positions = [];
+				var next_positions_index = 0;
+				var colors = [];
+				var indices_array = [];
+
+				// --------------------------------
+				var iteration_count = 4;
+				var rangle = 60 * Math.PI / 180.0;
+
+				function add_vertex(v) {
+
+					if (next_positions_index == 0xffff) throw new Error("Too many points");
+
+					positions.push(v.x, v.y, v.z);
+					colors.push(Math.random()*0.5+0.5, Math.random()*0.5+0.5, 1);
+					return next_positions_index++;
+				}
+
+				// simple Koch curve
+				function snowflake_iteration(p0, p4, depth) {
+
+					if (--depth < 0) {
+
+						var i = next_positions_index-1; // p0 already there
+						add_vertex(p4);
+						indices_array.push(i, i+1);
+						return;
+					}
+
+					var v = p4.clone().sub(p0);
+					var v_tier = v.clone().multiplyScalar(1.0/3.0);
+					var p1 = p0.clone().add(v_tier);
+
+					var angle = Math.atan2(v.y, v.x) + rangle;
+					var length = v_tier.length();
+					var p2 = p1.clone();
+					p2.x += Math.cos(angle) * length;
+					p2.y += Math.sin(angle) * length;
+
+					var p3 = p0.clone().add(v_tier).add(v_tier);
+
+					snowflake_iteration(p0, p1, depth);
+					snowflake_iteration(p1, p2, depth);
+					snowflake_iteration(p2, p3, depth);
+					snowflake_iteration(p3, p4, depth);
+				}
+
+				function snowflake(points, loop, x_offset) {
+
+					for (var iteration = 0; iteration != iteration_count; ++iteration) {
+
+						add_vertex(points[0]);
+						for (var p_index=0, p_count=points.length-1; p_index != p_count; ++p_index) {
+							snowflake_iteration(points[p_index], points[p_index+1], iteration);
+						}
+
+						if (loop) snowflake_iteration(points[points.length-1], points[0], iteration);
+
+						// translate input curve for next iteration
+						for (var p_index=0, p_count=points.length; p_index != p_count; ++p_index) {
+							points[p_index].x += x_offset;
+						}
+
+					}
+				}
+
+				var y = 0;
+				snowflake
+				(
+					[
+						new THREE.Vector3(0, y+0, 0),
+						new THREE.Vector3(500, y+0, 0)
+					],
+					false, 600
+				);
+
+				y += 600;
+				snowflake
+				(
+					[
+						new THREE.Vector3(0, y+0, 0),
+						new THREE.Vector3(250, y+400, 0),
+						new THREE.Vector3(500, y+0, 0)
+					],
+					true, 600
+				);
+
+				y += 600;
+				snowflake
+				(
+					[
+						new THREE.Vector3(0, y+0, 0),
+						new THREE.Vector3(500, y, 0),
+						new THREE.Vector3(500, y+500, 0),
+						new THREE.Vector3(0, y+500, 0),
+					],
+					true, 600
+				);
+
+				y += 1000;
+				snowflake
+				(
+					[
+						new THREE.Vector3(250, y+0, 0),
+						new THREE.Vector3(500, y+0, 0),
+						new THREE.Vector3(250, y+0, 0),
+						new THREE.Vector3(250, y+250, 0),
+						new THREE.Vector3(250, y+0, 0),
+						new THREE.Vector3(0, y, 0),
+						new THREE.Vector3(250, y+0, 0),
+						new THREE.Vector3(250, y-250, 0),
+						new THREE.Vector3(250, y+0, 0),
+					],
+					false, 600
+				);
+				// --------------------------------
+
+				geometry.addAttribute( 'position', Float32Array, positions.length, 3 );
+				geometry.attributes.position.array = new Float32Array(positions);
+
+				geometry.addAttribute( 'color', Float32Array, colors.length, 3 );
+				geometry.attributes.color.array = new Float32Array(colors);
+
+				geometry.addAttribute( 'index', Uint16Array, indices_array.length, 1 );
+				geometry.attributes.index.array = new Uint16Array(indices_array);
+				geometry.offsets = [ {start:0, index:0, count:indices_array.length} ];
+
+				geometry.computeBoundingSphere();
+
+				mesh = new THREE.Line( geometry, material, THREE.LinePieces);
+				mesh.position.x -= 1200;
+				mesh.position.y -= 1200;
+
+				parent_node = new THREE.Object3D();
+				parent_node.add(mesh);
+
+				scene.add( parent_node );
+
+				renderer = new THREE.WebGLRenderer( { antialias: false } );
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+				renderer.gammaInput = true;
+				renderer.gammaOutput = true;
+
+				container.appendChild( renderer.domElement );
+
+				//
+
+				stats = new Stats();
+				stats.domElement.style.position = 'absolute';
+				stats.domElement.style.top = '0px';
+				container.appendChild( stats.domElement );
+
+				//
+
+				window.addEventListener( 'resize', onWindowResize, false );
+
+			}
+
+			function onWindowResize() {
+
+				camera.aspect = window.innerWidth / window.innerHeight;
+				camera.updateProjectionMatrix();
+
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+			}
+
+			//
+
+			function animate() {
+
+				requestAnimationFrame( animate );
+
+				render();
+				stats.update();
+
+			}
+
+			function render() {
+
+				var time = Date.now() * 0.001;
+
+				//mesh.rotation.x = time * 0.25;
+				//mesh.rotation.y = time * 0.5;
+				parent_node.rotation.z = time * 0.5;
+
+				renderer.render( scene, camera );
+
+			}
+
+		</script>
+
+	</body>
+</html>

+ 75 - 25
src/renderers/WebGLRenderer.js

@@ -2382,6 +2382,45 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	};
 
+	// used by renderBufferDirect for THREE.Line
+	function setupLinesVertexAttributes( material, programAttributes, geometryAttributes, startIndex ) {
+
+		var attributeItem, attributeName, attributePointer, attributeSize;
+
+		for ( attributeName in programAttributes ) {
+
+			attributePointer = programAttributes[ attributeName ];
+			attributeItem = geometryAttributes[ attributeName ];
+			
+			if ( attributePointer >= 0 ) {
+
+				if ( attributeItem ) {
+
+					attributeSize = attributeItem.itemSize;
+					_gl.bindBuffer( _gl.ARRAY_BUFFER, attributeItem.buffer );
+					enableAttribute( attributePointer );
+					_gl.vertexAttribPointer( attributePointer, attributeSize, _gl.FLOAT, false, 0, startIndex * attributeSize * 4 ); // 4 bytes per Float32
+
+				} else if ( material.defaultAttributeValues ) {
+
+					if ( material.defaultAttributeValues[ attributeName ].length === 2 ) {
+
+						_gl.vertexAttrib2fv( attributePointer, material.defaultAttributeValues[ attributeName ] );
+
+					} else if ( material.defaultAttributeValues[ attributeName ].length === 3 ) {
+
+						_gl.vertexAttrib3fv( attributePointer, material.defaultAttributeValues[ attributeName ] );
+
+					}
+
+				}
+
+			}
+
+		}
+
+	}
+
 	function setDirectBuffers ( geometry, hint, dispose ) {
 
 		var attributes = geometry.attributes;
@@ -2721,54 +2760,65 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		} else if ( object instanceof THREE.Line ) {
 
-			if ( updateBuffers ) {
+			var primitives = ( object.type === THREE.LineStrip ) ? _gl.LINE_STRIP : _gl.LINES;
 
-				for ( attributeName in programAttributes ) {
+			setLineWidth( material.linewidth );
 
-					attributePointer = programAttributes[ attributeName ];
-					attributeItem = geometryAttributes[ attributeName ];
-					
-					if ( attributePointer >= 0 ) {
+			var index = geometryAttributes[ "index" ];
 
-						if ( attributeItem ) {
+			// indexed lines
+			
+			if ( index ) {
 
-							attributeSize = attributeItem.itemSize;
-							_gl.bindBuffer( _gl.ARRAY_BUFFER, attributeItem.buffer );
-							enableAttribute( attributePointer );
-							_gl.vertexAttribPointer( attributePointer, attributeSize, _gl.FLOAT, false, 0, 0 );
+				var offsets = geometry.offsets;
 
-						} else if ( material.defaultAttributeValues && material.defaultAttributeValues[ attributeName ] ) {
+				// if there is more than 1 chunk
+				// must set attribute pointers to use new offsets for each chunk
+				// even if geometry and materials didn't change
 
-							if ( material.defaultAttributeValues[ attributeName ].length === 2 ) {
+				if ( offsets.length > 1 ) updateBuffers = true;
 
-								_gl.vertexAttrib2fv( attributePointer, material.defaultAttributeValues[ attributeName ] );
+				for ( var i = 0, il = offsets.length; i < il; i ++ ) {
 
-							} else if ( material.defaultAttributeValues[ attributeName ].length === 3 ) {
+					var startIndex = offsets[ i ].index;
 
-								_gl.vertexAttrib3fv( attributePointer, material.defaultAttributeValues[ attributeName ] );
+					if ( updateBuffers ) {
 
-							}
+						setupLinesVertexAttributes(material, programAttributes, geometryAttributes, startIndex);
 
-						}
+						// indices
+						_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, index.buffer );
 
 					}
 
+					// render indexed lines
+
+					_gl.drawElements( _gl.LINES, offsets[ i ].count, _gl.UNSIGNED_SHORT, offsets[ i ].start * 2 ); // 2 bytes per Uint16Array
+
+					_this.info.render.calls ++;
+					_this.info.render.vertices += offsets[ i ].count; // not really true, here vertices can be shared
+
 				}
 
 			}
 
-			// render lines
+			// non-indexed lines
 
-			var primitives = ( object.type === THREE.LineStrip ) ? _gl.LINE_STRIP : _gl.LINES;
+			else {
 
-			setLineWidth( material.linewidth );
+				if ( updateBuffers ) {
 
-			var position = geometryAttributes[ "position" ];
+					setupLinesVertexAttributes(material, programAttributes, geometryAttributes, 0);
+				}
+
+				var position = geometryAttributes[ "position" ];
+
+				_gl.drawArrays( primitives, 0, position.numItems / 3 );
+				_this.info.render.calls ++;
+				_this.info.render.points += position.numItems;
+			}
 
-			_gl.drawArrays( primitives, 0, position.numItems / 3 );
 
-			_this.info.render.calls ++;
-			_this.info.render.points += position.numItems;
 
 		}