Tentone 6 lat temu
rodzic
commit
81260faf1b

+ 182 - 0
examples/js/exporters/DracoExporter.js

@@ -0,0 +1,182 @@
+'use strict';
+
+/**
+ * Export draco compressed files from threejs geometry objects.
+ *
+ * Draco files are compressed and usually are smaller than conventional 3D file formats.
+ *
+ * @class DracoExporter
+ * @author syed-usman
+ * @author tentone
+ */
+
+THREE.DracoExporter = function () {};
+
+THREE.DracoExporter.prototype = {
+
+	constructor: THREE.DracoExporter,
+
+	parse: function ( geometry, options ) {
+
+		if ( DracoEncoderModule === undefined ) {
+
+			throw new Error( 'THREE.DracoExporter: required the draco_decoder to work.' );
+
+		}
+
+		if ( options === undefined ) {
+
+			options = {
+
+				decodeSpeed: 5,
+				encodeSpeed: 5,
+				encoderMethod: THREE.DracoExporter.MESH_EDGEBREAKER_ENCODING,
+				quantization: [ 16, 8, 8, 8, 16 ]
+
+			};
+
+		}
+
+		if ( geometry.isBufferGeometry === true ) {
+
+			var convert = new THREE.Geometry();
+			convert.fromBufferGeometry( geometry );
+			geometry = convert;
+
+		}
+
+		var dracoEncoder = DracoEncoderModule();
+
+		var encoder = new dracoEncoder.Encoder();
+		var builder = new dracoEncoder.MeshBuilder();
+		var mesh = new dracoEncoder.Mesh();
+
+		var numFaces = geometry.faces.length;
+		var numPoints = geometry.vertices.length;
+		var numIndices = numFaces * 3;
+
+		var indices = new Uint32Array( numIndices );
+		var vertices = new Float32Array( geometry.vertices.length * 3 );
+		var normals = new Float32Array( geometry.vertices.length * 3 );
+
+		// Faces
+
+		for ( var i = 0; i < numFaces; i ++ ) {
+
+			var index = i * 3;
+			indices[ index ] = geometry.faces[ i ].a;
+			indices[ index + 1 ] = geometry.faces[ i ].b;
+			indices[ index + 2 ] = geometry.faces[ i ].c;
+
+		}
+
+		builder.AddFacesToMesh( mesh, numFaces, indices );
+
+		// Vertex
+
+		for ( var i = 0; i < geometry.vertices.length; i ++ ) {
+
+			var index = i * 3;
+			vertices[ index ] = geometry.vertices[ i ].x;
+			vertices[ index + 1 ] = geometry.vertices[ i ].y;
+			vertices[ index + 2 ] = geometry.vertices[ i ].z;
+
+		}
+
+		builder.AddFloatAttributeToMesh( mesh, dracoEncoder.POSITION, numPoints, 3, vertices );
+
+		// Normals
+
+		for ( var face of geometry.faces ) {
+
+			normals[ face[ 'a' ] * 3 ] = face.vertexNormals[ 0 ].x;
+			normals[ ( face[ 'a' ] * 3 ) + 1 ] = face.vertexNormals[ 0 ].y;
+			normals[ ( face[ 'a' ] * 3 ) + 2 ] = face.vertexNormals[ 0 ].z;
+
+			normals[ face[ 'b' ] * 3 ] = face.vertexNormals[ 1 ].x;
+			normals[ ( face[ 'b' ] * 3 ) + 1 ] = face.vertexNormals[ 1 ].y;
+			normals[ ( face[ 'b' ] * 3 ) + 2 ] = face.vertexNormals[ 1 ].z;
+
+			normals[ face[ 'c' ] * 3 ] = face.vertexNormals[ 2 ].x;
+			normals[ ( face[ 'c' ] * 3 ) + 1 ] = face.vertexNormals[ 2 ].y;
+			normals[ ( face[ 'c' ] * 3 ) + 2 ] = face.vertexNormals[ 2 ].z;
+
+		}
+
+		builder.AddFloatAttributeToMesh( mesh, dracoEncoder.NORMAL, numPoints, 3, normals );
+
+		//Compress using draco encoder
+
+		var encodedData = new dracoEncoder.DracoInt8Array();
+
+		//Sets the desired encoding and decoding speed for the given options from 0 (slowest speed, but the best compression) to 10 (fastest, but the worst compression).
+
+		encoder.SetSpeedOptions( options.encodeSpeed || 5, options.decodeSpeed || 5 );
+
+		// Sets the desired encoding method for a given geometry.
+
+		if ( options.encoderMethod !== undefined ) {
+
+			encoder.SetEncodingMethod( options.encoderMethod );
+
+		}
+
+		// Sets the quantization (number of bits used to represent) compression options for a named attribute.
+		// The attribute values will be quantized in a box defined by the maximum extent of the attribute values.
+
+		for ( var i = 0; i < 5; i ++ ) {
+
+			if ( options.quantization[ i ] !== undefined ) {
+
+				encoder.SetAttributeQuantization( i, options.quantization[ i ] );
+
+			}
+
+		}
+
+		var length = encoder.EncodeMeshToDracoBuffer( mesh, encodedData );
+		dracoEncoder.destroy( mesh );
+
+		if ( length === 0 ) {
+
+			throw new Error( 'THREE.DracoExporter: Draco encoding failed' );
+
+		}
+
+		//Copy encoded data to buffer.
+		var outputData = new Int8Array( new ArrayBuffer( length ) );
+
+		for ( var i = 0; i < length; i ++ ) {
+
+			outputData[ i ] = encodedData.GetValue( i );
+
+		}
+
+		dracoEncoder.destroy( encodedData );
+		dracoEncoder.destroy( encoder );
+		dracoEncoder.destroy( builder );
+
+		return outputData;
+
+	}
+
+};
+
+// Encoder methods
+
+THREE.DracoExporter.MESH_EDGEBREAKER_ENCODING = 1;
+THREE.DracoExporter.MESH_SEQUENTIAL_ENCODING = 0;
+
+// Geometry type
+
+THREE.DracoExporter.POINT_CLOUD = 0;
+THREE.DracoExporter.TRIANGULAR_MESH = 1;
+
+// Attribute type
+
+THREE.DracoExporter.INVALID = - 1;
+THREE.DracoExporter.POSITION = 0;
+THREE.DracoExporter.NORMAL = 1;
+THREE.DracoExporter.COLOR = 2;
+THREE.DracoExporter.TEX_COORD = 3;
+THREE.DracoExporter.GENERIC = 4;

Plik diff jest za duży
+ 3 - 0
examples/js/libs/draco/draco_encoder.js


+ 168 - 0
examples/misc_exporter_draco.html

@@ -0,0 +1,168 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js webgl - exporter - stl</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: #000;
+				color: #fff;
+				margin: 0px;
+				overflow: hidden;
+			}
+			#info {
+				color: #fff;
+				position: absolute;
+				top: 10px;
+				width: 100%;
+				text-align: center;
+				display:block;
+			}
+			#info a {
+				color: #046;
+				font-weight: bold;
+			}
+		</style>
+	</head>
+	<body>
+		<div id="info">
+			<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> webgl - exporter - draco<br/><br/> <button onclick="exportFile()">export</button>
+		</div>
+
+		<script src="../build/three.js"></script>
+		
+		<script src="js/libs/draco/draco_encoder.js"></script>
+
+		<script src="js/controls/OrbitControls.js"></script>
+		<script src="js/exporters/DracoExporter.js"></script>
+
+		<script src="js/WebGL.js"></script>
+
+		<script>
+
+			if ( WEBGL.isWebGLAvailable() === false ) {
+
+				document.body.appendChild( WEBGL.getWebGLErrorMessage() );
+
+			}
+
+			var scene, camera, renderer, exporter, mesh;
+
+			init();
+			animate();
+
+			function init() {
+
+				camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );
+				camera.position.set( 200, 100, 200 );
+
+				scene = new THREE.Scene();
+				scene.background = new THREE.Color( 0xa0a0a0 );
+				scene.fog = new THREE.Fog( 0xa0a0a0, 200, 1000 );
+
+				exporter = new THREE.DracoExporter();
+
+				//
+
+				var hemiLight = new THREE.HemisphereLight( 0xffffff, 0x444444 );
+				hemiLight.position.set( 0, 200, 0 );
+				scene.add( hemiLight );
+
+				var directionalLight = new THREE.DirectionalLight( 0xffffff );
+				directionalLight.position.set( 0, 200, 100 );
+				directionalLight.castShadow = true;
+				directionalLight.shadow.camera.top = 180;
+				directionalLight.shadow.camera.bottom = - 100;
+				directionalLight.shadow.camera.left = - 120;
+				directionalLight.shadow.camera.right = 120;
+				scene.add( directionalLight );
+
+				// ground
+
+				var ground = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2000, 2000 ), new THREE.MeshPhongMaterial( { color: 0x999999, depthWrite: false } ) );
+				ground.rotation.x = - Math.PI / 2;
+				ground.receiveShadow = true;
+				scene.add( ground );
+
+				var grid = new THREE.GridHelper( 2000, 20, 0x000000, 0x000000 );
+				grid.material.opacity = 0.2;
+				grid.material.transparent = true;
+				scene.add( grid );
+
+				// export mesh
+
+				var geometry = new THREE.TorusKnotGeometry( 50, 15, 200, 30 );
+				var material = new THREE.MeshPhongMaterial( { color: 0x00ff00 } );
+
+				mesh = new THREE.Mesh( geometry, material );
+				mesh.castShadow = true;
+				mesh.position.y = 25;
+				scene.add( mesh );
+
+				//
+
+				renderer = new THREE.WebGLRenderer( { antialias: true } );
+				renderer.setPixelRatio( window.devicePixelRatio );
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				renderer.shadowMap.enabled = true;
+				document.body.appendChild( renderer.domElement );
+
+				//
+
+				var controls = new THREE.OrbitControls( camera, renderer.domElement );
+				controls.target.set( 0, 25, 0 );
+				controls.update();
+
+				//
+
+				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 );
+				renderer.render( scene, camera );
+
+			}
+
+			function exportFile() {
+
+				var result = exporter.parse( mesh.geometry );
+				saveArrayBuffer( result, 'file.drc' );
+
+			}
+
+			var link = document.createElement( 'a' );
+			link.style.display = 'none';
+			document.body.appendChild( link );
+
+			function save( blob, filename ) {
+
+				link.href = URL.createObjectURL( blob );
+				link.download = filename;
+				link.click();
+
+			}
+
+			function saveArrayBuffer( buffer, filename ) {
+
+				save( new Blob( [ buffer ], { type: 'application/octet-stream' } ), filename );
+
+			}
+
+		</script>
+
+	</body>
+</html>

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików