فهرست منبع

Added breaking of mesh into chunks of max 64K vertices (done in materials sorting step).

alteredq 15 سال پیش
والد
کامیت
406063d588
2فایلهای تغییر یافته به همراه351 افزوده شده و 8 حذف شده
  1. 319 0
      examples/large_mesh_test.html
  2. 32 8
      src/objects/Mesh.js

+ 319 - 0
examples/large_mesh_test.html

@@ -0,0 +1,319 @@
+<!DOCTYPE HTML>
+<html lang="en">
+	<head>
+		<title>three.js - Large mesh test</title>
+		<meta charset="utf-8">
+		<style type="text/css">
+			body {
+				background:#000;
+				color:#fff;
+				padding:0;
+				margin:0;
+				overflow:hidden;
+				font-family:georgia;
+				text-align:center;
+			}
+			h1 { }
+			a { color:skyblue }
+			canvas { pointer-events:none; z-index:10; position:relative; }
+			#log { position:absolute; top:50px; text-align:left; display:block; z-index:100 }
+			#d { text-align:center; margin:1em 0 -18em 0; z-index:0; position:relative; display:block }
+			.button { background:orange; color:#fff; padding:0.2em 0.5em; cursor:pointer }
+			.inactive { background:#999; color:#eee }
+		</style>
+	</head>
+	
+	<body>
+		<div id="d">
+			<h1>Large mesh test</h1>
+
+			<span id="rcanvas" class="button inactive">2d canvas renderer</span>
+			<span id="rwebgl" class="button">WebGL renderer</span>
+			<br/>
+			
+			<p>Lucy model from <a href="http://graphics.stanford.edu/data/3Dscanrep/">Stanford 3d scanning repository</a> 
+			(decimated with <a href="http://meshlab.sourceforge.net/">Meshlab</a>).
+			
+			<p>Please be patient while the mesh is loading. It may take a while, it's 4.5MB file.
+			<p>Using a modified version of <a href="http://github.com/alteredq/three.js">Three.js</a> by mrdoob.
+			
+			<br/>
+			<p>Best viewed in Chrome 8/9 or Firefox 4 using WebGL renderer.
+			<p>Canvas renderer is very slow for this demo and only diffuse material works there.
+		</div>
+		
+		<pre id="log"></pre>
+
+		<!--
+		<script type="text/javascript" src="../build/Three.js"></script> 
+		-->
+
+		<script type="text/javascript" src="../src/Three.js"></script>
+		<script type="text/javascript" src="../src/core/Color.js"></script>
+		<script type="text/javascript" src="../src/core/Vector2.js"></script>
+		<script type="text/javascript" src="../src/core/Vector3.js"></script>
+		<script type="text/javascript" src="../src/core/Vector4.js"></script>
+		<script type="text/javascript" src="../src/core/Rectangle.js"></script>
+		<script type="text/javascript" src="../src/core/Matrix3.js"></script>
+		<script type="text/javascript" src="../src/core/Matrix4.js"></script>
+		<script type="text/javascript" src="../src/core/Vertex.js"></script>
+		<script type="text/javascript" src="../src/core/Face3.js"></script>
+		<script type="text/javascript" src="../src/core/Face4.js"></script>
+		<script type="text/javascript" src="../src/core/UV.js"></script>
+		<script type="text/javascript" src="../src/core/Geometry.js"></script>
+		<script type="text/javascript" src="../src/cameras/Camera.js"></script>
+		<script type="text/javascript" src="../src/lights/Light.js"></script>
+		<script type="text/javascript" src="../src/lights/AmbientLight.js"></script>
+		<script type="text/javascript" src="../src/lights/DirectionalLight.js"></script>
+		<script type="text/javascript" src="../src/lights/PointLight.js"></script>
+		<script type="text/javascript" src="../src/objects/Object3D.js"></script>
+		<script type="text/javascript" src="../src/objects/Mesh.js"></script>
+		<script type="text/javascript" src="../src/objects/Particle.js"></script>
+		<script type="text/javascript" src="../src/objects/Line.js"></script>
+		<script type="text/javascript" src="../src/materials/LineColorMaterial.js"></script>
+		<script type="text/javascript" src="../src/materials/MeshPhongMaterial.js"></script>
+		<script type="text/javascript" src="../src/materials/MeshBitmapMaterial.js"></script>
+		<script type="text/javascript" src="../src/materials/MeshColorFillMaterial.js"></script>
+		<script type="text/javascript" src="../src/materials/MeshColorStrokeMaterial.js"></script>
+		<script type="text/javascript" src="../src/materials/MeshFaceMaterial.js"></script>
+		<script type="text/javascript" src="../src/materials/ParticleCircleMaterial.js"></script>
+		<script type="text/javascript" src="../src/materials/ParticleBitmapMaterial.js"></script>
+		<script type="text/javascript" src="../src/scenes/Scene.js"></script>
+		<script type="text/javascript" src="../src/renderers/Projector.js"></script>
+		<script type="text/javascript" src="../src/renderers/CanvasRenderer.js"></script>
+		<script type="text/javascript" src="../src/renderers/SVGRenderer.js"></script>
+		<script type="text/javascript" src="../src/renderers/WebGLRenderer.js"></script>
+		<script type="text/javascript" src="../src/renderers/renderables/RenderableFace3.js"></script>
+		<script type="text/javascript" src="../src/renderers/renderables/RenderableFace4.js"></script>
+		<script type="text/javascript" src="../src/renderers/renderables/RenderableParticle.js"></script>
+		<script type="text/javascript" src="../src/renderers/renderables/RenderableLine.js"></script>
+		<!--
+		-->
+		
+		<script type="text/javascript" src="geometry/primitives/Sphere.js"></script>
+
+		<script type="text/javascript" src="js/Stats.js"></script>
+
+		<script type="text/javascript">
+
+			var SCREEN_WIDTH = window.innerWidth;
+			var SCREEN_HEIGHT = window.innerHeight;
+			var FLOOR = -250;
+
+			var container;
+			var stats;
+
+			var camera;
+			var scene;
+			var canvasRenderer, webglRenderer;
+
+			var mesh, zmesh, lightMesh, geometry;
+			
+			var directionalLight, pointLight;
+			
+			var mouseX = 0;
+			var mouseY = 0;
+
+			var windowHalfX = window.innerWidth >> 1;
+			var windowHalfY = window.innerHeight >> 1;
+
+			var render_canvas = 1, render_gl = 1;
+			var has_gl = 0;
+			
+			var bcanvas = document.getElementById("rcanvas");
+			var bwebgl = document.getElementById("rwebgl");
+			
+			document.addEventListener('mousemove', onDocumentMouseMove, false);
+
+			init();
+			
+			loop();
+			
+			render_canvas = !has_gl;
+			bwebgl.style.display = has_gl ? "inline" : "none";
+			bcanvas.className = render_canvas ? "button" : "button inactive";
+			
+			setInterval(loop, 1000/60);
+			
+			function addMesh( geometry, scale, x, y, z, rx, ry, rz, material ) {
+				
+				mesh = new THREE.Mesh( geometry, material );
+				mesh.scale.x = mesh.scale.y = mesh.scale.z = scale;
+				mesh.position.x = x;
+				mesh.position.y = y;
+				mesh.position.z = z;
+				mesh.rotation.x = rx;
+				mesh.rotation.y = ry;
+				mesh.rotation.z = rz;
+				mesh.overdraw = true;
+				mesh.updateMatrix();
+				scene.addObject(mesh);
+				
+			}
+			
+			function init() {
+
+				container = document.createElement('div');
+				document.body.appendChild(container);
+
+				camera = new THREE.Camera( 50, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 100000 );
+				camera.position.z = 1500;
+				camera.updateMatrix();
+
+				scene = new THREE.Scene();
+
+				// LIGHTS
+
+				var ambient = new THREE.AmbientLight( 0x101010 );
+				scene.addLight( ambient );
+
+				directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
+				directionalLight.position.x = 1;
+				directionalLight.position.y = 1;
+				directionalLight.position.z = 2;
+				directionalLight.position.normalize();
+				scene.addLight( directionalLight );
+
+				pointLight = new THREE.PointLight( 0xffaa00 );
+				pointLight.position.x = 0;
+				pointLight.position.y = 0;
+				pointLight.position.z = 0;
+				scene.addLight( pointLight );
+
+				// light representation
+				sphere = new Sphere( 100, 16, 8, 1 );
+				lightMesh = new THREE.Mesh( sphere, new THREE.MeshColorFillMaterial( 0xffaa00 ) );
+				lightMesh.scale.x = lightMesh.scale.y = lightMesh.scale.z = 0.05;
+				lightMesh.position = pointLight.position;
+				lightMesh.overdraw = true;
+				lightMesh.updateMatrix();
+				scene.addObject(lightMesh);
+				
+
+				if ( render_gl ) {
+					try {
+						webglRenderer = new THREE.WebGLRenderer( scene );
+						webglRenderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
+						container.appendChild( webglRenderer.domElement );
+						has_gl = 1;
+					}
+					catch (e) {
+					}
+				}
+				
+				if( render_canvas ) {
+					canvasRenderer = new THREE.CanvasRenderer();
+					canvasRenderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
+					container.appendChild( canvasRenderer.domElement );
+				}
+
+
+				stats = new Stats();
+				stats.domElement.style.position = 'absolute';
+				stats.domElement.style.top = '0px';
+				stats.domElement.style.zIndex = 100;
+				container.appendChild( stats.domElement );
+				
+				bcanvas.addEventListener("click", toggleCanvas, false);
+				bwebgl.addEventListener("click", toggleWebGL, false);
+
+				function createModel() {
+					
+					geometry = new Lucy100k( );
+					
+					addMesh( geometry, 0.75, 900, 0, 0, 0,0,0, new THREE.MeshPhongMaterial( 0x030303, 0x030303, 0x990000, 30, 1.0 ) );
+					addMesh( geometry, 0.75, 300, 0, 0, 0,0,0, new THREE.MeshFaceMaterial( ) );
+					addMesh( geometry, 0.75, -300, 0, 0, 0,0,0, new THREE.MeshPhongMaterial( 0x030303, 0x111111, 0xffaa00, 10, 1.0 )  );
+					addMesh( geometry, 0.75, -900, 0, 0, 0,0,0, new THREE.MeshPhongMaterial( 0x030303, 0x555555, 0x666666, 10, 1.0 )  );
+					
+					/*
+					log( "geometry.vertices: " + geometry.vertices.length );
+					log( "geometry.faces: " + geometry.faces.length );
+					*/
+
+				}
+
+				loadAsync( "obj/lucy/Lucy100k.js", createModel );
+
+			}
+
+			function loadAsync( url, callback ) {
+				
+				var el = document.createElement( 'script' );
+				el.type = 'text/javascript';
+				el.onload = callback;
+				el.src = url;
+				document.getElementsByTagName("head")[0].appendChild(el);
+
+			}
+
+			
+			function onDocumentMouseMove(event) {
+
+				mouseX = ( event.clientX - windowHalfX );
+				mouseY = ( event.clientY - windowHalfY );
+
+			}
+
+			var r = 0;
+			
+			function loop() {
+
+				camera.position.x += ( mouseX - camera.position.x ) * .05;
+				camera.position.y += ( - mouseY - camera.position.y ) * .05;
+				camera.updateMatrix();
+				
+				lightMesh.position.x = 700*Math.cos(r);
+				lightMesh.position.z = 700*Math.sin(r);
+				lightMesh.updateMatrix();
+
+				r += 0.01;
+				
+				
+				if ( render_canvas ) canvasRenderer.render( scene, camera );
+				if ( render_gl && has_gl ) webglRenderer.render( scene, camera );
+
+				stats.update();
+
+			}
+
+			function log(text) {
+			
+				var e = document.getElementById("log");
+				e.innerHTML = text + "<br/>" + e.innerHTML;
+				
+			}
+			
+			function toggleCanvas() {
+			
+				render_canvas = !render_canvas;
+				bcanvas.className = render_canvas ? "button" : "button inactive";
+				
+				render_gl = !render_canvas;
+				bwebgl.className = render_gl ? "button" : "button inactive";
+				
+				if( has_gl )
+					webglRenderer.domElement.style.display = render_gl ? "block" : "none";
+				
+				canvasRenderer.domElement.style.display = render_canvas ? "block" : "none";
+				
+			}
+			
+			function toggleWebGL() {
+			
+				render_gl = !render_gl;
+				bwebgl.className = render_gl ? "button" : "button inactive";
+				
+				render_canvas = !render_gl;
+				bcanvas.className = render_canvas ? "button" : "button inactive";
+				
+				if( has_gl )
+					webglRenderer.domElement.style.display = render_gl ? "block" : "none";
+					
+				canvasRenderer.domElement.style.display = render_canvas ? "block" : "none";
+				
+			}
+		</script>
+
+	</body>
+</html>

+ 32 - 8
src/objects/Mesh.js

@@ -32,11 +32,11 @@ THREE.Mesh.prototype.sortFacesByMaterial = function () {
 	// which could then use vertex color attributes instead of each being
 	// in its separate VBO
 
-	var i, l, f, fl, face, material, hash_array;
+	var i, l, f, fl, face, material, vertices, mhash, ghash, hash_map = {};
 
 	function materialHash( material ) {
 
-		hash_array = [];
+		var hash_array = [];
 
 		for ( i = 0, l = material.length; i < l; i++ ) {
 
@@ -60,20 +60,44 @@ THREE.Mesh.prototype.sortFacesByMaterial = function () {
 
 		face = this.geometry.faces[ f ];
 		material = face.material;
+		
+		mhash = materialHash( material );
 
-		hash = materialHash( material);
+		if ( hash_map[ mhash ] == undefined ) {
+			
+			hash_map[ mhash ] = { 'hash': mhash, 'counter': 0 };
+		}
+
+		ghash = hash_map[ mhash ].hash + "_" + hash_map[ mhash ].counter;
 
-		if ( this.materialFaceGroup[ hash ] == undefined ) {
+		if ( this.materialFaceGroup[ ghash ] == undefined ) {
 
-			this.materialFaceGroup[ hash ] = { 'faces': [], 'material': material };
+			this.materialFaceGroup[ ghash ] = { 'faces': [], 'material': material, 'vertices': 0 };
 
 		}
+		
+		vertices = face instanceof THREE.Face3 ? 3 : 4;
+
+		if ( this.materialFaceGroup[ ghash ].vertices + vertices > 65535 ) {
+			
+			hash_map[ mhash ].counter += 1;
+			ghash = hash_map[ mhash ].hash + "_" + hash_map[ mhash ].counter;
+			
+			if ( this.materialFaceGroup[ ghash ] == undefined ) {
+
+				this.materialFaceGroup[ ghash ] = { 'faces': [], 'material': material, 'vertices': 0 };
 
-		this.materialFaceGroup[ hash ].faces.push( f );
+			}
+			
+		}
+		
+		this.materialFaceGroup[ ghash ].faces.push( f );
+		this.materialFaceGroup[ ghash ].vertices += vertices;
+		
 
 	}
 
-}
+};
 
 THREE.Mesh.prototype.normalizeUVs = function () {
 
@@ -95,4 +119,4 @@ THREE.Mesh.prototype.normalizeUVs = function () {
 
 	}
 
-}
+};

粤ICP备19079148号