Pārlūkot izejas kodu

Ahhhh! It works!!!

Luis Fraguada 5 gadi atpakaļ
vecāks
revīzija
79c661e025

+ 220 - 43
examples/jsm/loaders/3DMLoader.js

@@ -16,9 +16,18 @@ var Rhino3dmLoader = function ( manager ) {
 	this.libraryPath = '';
 	this.libraryPending = null;
 	this.libraryBinary = null;
+	this.libraryConfig = {};
+
+	this.workerLimit = 4;
+	this.workerPool = [];
+	this.workerNextTaskID = 1;
+	this.workerSourceURL = '';
+	this.workerConfig = {};
 
 };
 
+Rhino3dmLoader.taskCache = new WeakMap();
+
 Rhino3dmLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
 
     constructor: Rhino3dmLoader,
@@ -31,36 +40,99 @@ Rhino3dmLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
 
 	},
 
+	setWorkerLimit: function ( workerLimit ) {
+
+		this.workerLimit = workerLimit;
+
+		return this;
+
+	},
+
 	load: function ( url, onLoad, onProgress, onError ) {
 
-		var scope = this;
+		var loader = new FileLoader( this.manager );
 
-		var path = ( this.path !== undefined ) ? this.path : LoaderUtils.extractUrlBase( url );
+		loader.setPath( this.path );
+		loader.setResponseType( 'arraybuffer' );
 
-		var loader = new FileLoader( scope.manager );
+		loader.load( url, ( buffer ) => {
 
-		loader.load( url, function ( text ) {
+			// Check for an existing task using this buffer. A transferred buffer cannot be transferred
+			// again from this thread.
+			if ( Rhino3dmLoader.taskCache.has( buffer ) ) {
 
-			try {
+				var cachedTask = Rhino3dmLoader.taskCache.get( buffer );
 
-				scope.parse( text, path, onLoad, onError );
+				return cachedTask.promise.then( onLoad ).catch( onError );
 
-			} catch ( e ) {
+			}
+
+			this.decodeObjects( buffer, url )
+				.then( onLoad )
+				.catch( onError );
+
+		}, onProgress, onError );
+
+
+	},
 
-				if ( onError !== undefined ) {
+	debug: function () {
+
+		console.log( 'Task load: ', this.workerPool.map( ( worker ) => worker._taskLoad ) );
+
+	},
+
+	decodeObjects: function ( buffer, url ) {
+
+		var worker;
+		var taskID;
+
+		var taskCost = buffer.byteLength;
+
+		var objectPending = this._getWorker( taskCost )
+			.then( ( _worker ) => {
+
+				worker = _worker;
+				taskID = this.workerNextTaskID ++; //hmmm
+
+				return new Promise( ( resolve, reject ) => {
+
+					worker._callbacks[ taskID ] = { resolve, reject };
+
+					worker.postMessage( { type: 'decode', id: taskID, buffer }, [ buffer ] );
+
+					//this.debug();
+
+				} );
 
-					onError( e );
+			} )
+			.then( ( message ) => this._createGeometry( message.geometry ) );
 
-				} else {
+		// Remove task from the task list.
+		// Note: replaced '.finally()' with '.catch().then()' block - iOS 11 support (#19416)
+		objectPending
+			.catch( () => true )
+			.then( () => {
 
-					throw e;
+				if ( worker && taskID ) {
+
+					this._releaseTask( worker, taskID );
+
+					//this.debug();
 
 				}
 
-			}
+			} );
 
-		}, onProgress, onError );
+		// Cache the task result.
+		Rhino3dmLoader.taskCache.set( buffer, {
+
+			url: url,
+			promise: objectPending
+
+		} );
 
+		return objectPending;
 	},
 
 	parse: function ( ) {
@@ -70,11 +142,36 @@ Rhino3dmLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
 
 	},
 
+	_createGeometry: function ( geometryData ) {
+
+		var geometry = new BufferGeometry();
+
+		if ( geometryData.index ) {
+
+			geometry.setIndex( new BufferAttribute( geometryData.index.array, 1 ) );
+
+		}
+
+		for ( var i = 0; i < geometryData.attributes.length; i ++ ) {
+
+			var attribute = geometryData.attributes[ i ];
+			var name = attribute.name;
+			var array = attribute.array;
+			var itemSize = attribute.itemSize;
+
+			geometry.setAttribute( name, new BufferAttribute( array, itemSize ) );
+
+		}
+
+		return geometry;
+
+	},
+
 	_initLibrary: function () {
 
 		if ( ! this.libraryPending ) {
 
-			// Load transcoder wrapper.
+			// Load rhino3dm wrapper.
 			var jsLoader = new FileLoader( this.manager );
 			jsLoader.setPath( this.libraryPath );
 			var jsContent = new Promise( ( resolve, reject ) => {
@@ -83,7 +180,7 @@ Rhino3dmLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
 
 			} );
 
-			// Load transcoder WASM binary.
+			// Load rhino3dm WASM binary.
 			var binaryLoader = new FileLoader( this.manager );
 			binaryLoader.setPath( this.libraryPath );
 			binaryLoader.setResponseType( 'arraybuffer' );
@@ -96,6 +193,9 @@ Rhino3dmLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
 			this.libraryPending = Promise.all( [ jsContent, binaryContent ] )
 				.then( ( [ jsContent, binaryContent ] ) => {
 
+					//this.libraryBinary = binaryContent;
+					this.libraryConfig.wasmBinary = binaryContent;
+
 					var fn = Rhino3dmLoader.Rhino3dmWorker.toString();
 
 					var body = [
@@ -106,7 +206,6 @@ Rhino3dmLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
 					].join( '\n' );
 
 					this.workerSourceURL = URL.createObjectURL( new Blob( [ body ] ) );
-					this.libraryBinary = binaryContent;
 
 				} );
 
@@ -114,16 +213,98 @@ Rhino3dmLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
 
 		return this.libraryPending;
 
+	},
+
+	_getWorker: function ( taskCost ) {
+
+		return this._initLibrary().then( () => {
+
+			if ( this.workerPool.length < this.workerLimit ) {
+
+				var worker = new Worker( this.workerSourceURL );
+
+				worker._callbacks = {};
+				worker._taskCosts = {};
+				worker._taskLoad = 0;
+
+				worker.postMessage( {
+					type: 'init',
+					libraryConfig: this.libraryConfig
+				} );
+
+				worker.onmessage = function ( e ) {
+
+					var message = e.data;
+
+					switch ( message.type ) {
+
+						case 'decode':
+							worker._callbacks[ message.id ].resolve( message );
+							break;
+
+						case 'error':
+							worker._callbacks[ message.id ].reject( message );
+							break;
+
+						default:
+							console.error( 'THREE.Rhino3dmLoader: Unexpected message, "' + message.type + '"' );
+
+					}
+
+				};
+
+				this.workerPool.push( worker );
+
+			} else {
+
+				this.workerPool.sort( function ( a, b ) {
+
+					return a._taskLoad > b._taskLoad ? - 1 : 1;
+
+				} );
+
+			}
+
+			var worker = this.workerPool[ this.workerPool.length - 1 ];
+
+			worker._taskLoad += taskCost;
+
+			return worker;
+
+		} );
+	},
+
+	_releaseTask: function ( worker, taskID ) {
+
+		worker._taskLoad -= worker._taskCosts[ taskID ];
+		delete worker._callbacks[ taskID ];
+		delete worker._taskCosts[ taskID ];
+
+	},
+
+	dispose: function () {
+
+		for ( var i = 0; i < this.workerPool.length; ++ i ) {
+
+			this.workerPool[ i ].terminate();
+
+		}
+
+		this.workerPool.length = 0;
+
+		return this;
+
 	}
+
 } );
 
 /* WEB WORKER */
 
 Rhino3dmLoader.Rhino3dmWorker = function () {
 
-	var libraryConfig;
 	var libraryPending;
-	var _RhinoFile;
+	var libraryConfig;
+	var rhino;
 
 	onmessage = function ( e ) {
 
@@ -132,42 +313,38 @@ Rhino3dmLoader.Rhino3dmWorker = function () {
 		switch ( message.type ) {
 
 			case 'init':
-				libraryPending = new Promise( function ( resolve/*, reject*/ ) {
-
-					libraryPending.onModuleLoaded = function ( draco ) {
 
-						// Module is Promise-like. Wrap before resolving to avoid loop.
-						resolve( { rhino3dm: rhino3dm } );
+				libraryConfig = message.libraryConfig;
+				var wasmBinary = libraryConfig.wasmBinary;
+				var RhinoModule;
+				libraryPending = new Promise( function ( resolve ) { 
 
-					};
+					/* Like Basis Loader */
+					RhinoModule = { wasmBinary, onRuntimeInitialized: resolve };
 
-					//DracoDecoderModule( decoderConfig );
+					rhino3dm( RhinoModule );
 
-				} );
-				break;
-			case 'decode':
-				break;
-		}
-	}
-
-	function init( wasmBinary ) {
 
-		var rhino3dmModule;
-		libraryPending = new Promise( ( resolve ) => {
+				 } ).then( () => {
 
-			rhino3dmModule = { wasmBinary, onRuntimeInitialized: resolve };
-			//BASIS( rhino3dmModule );
+					rhino = RhinoModule;
 
-		} ).then( () => {
-
-			var { BasisFile, initializeBasis } = rhino3dmModule;
+				 });
+				 
+				break;
 
-			_RhinoFile = BasisFile;
+			case 'decode':
 
-			//initializeBasis();
+				libraryPending.then( () => { 
 
-		} );
+					// TODO
+					let sphere = new rhino.Sphere([0,0,0], 10);
+					console.log(sphere.radius);
 
+				} );
+				
+				break;
+		}
 	}
 
 };

BIN
examples/models/3dm/hello_mesh.3dm


+ 6 - 5
examples/webgl_loader_3dm.html

@@ -9,15 +9,15 @@
 
 	<body>
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - 3DS loader
+			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - Rhino 3DM loader
 		</div>
 
 		<script type="module">
 
 			import * as THREE from '../build/three.module.js';
 
-			import { TrackballControls } from './jsm/controls/TrackballControls.js';
-			import { Rhino3dmLoader } from './jsm/loaders/3dmLoader.js';
+			import { OrbitControls } from './jsm/controls/OrbitControls.js';
+			import { Rhino3dmLoader } from './jsm/loaders/3DMLoader.js';
 
 			var container, controls;
 			var camera, scene, renderer;
@@ -41,8 +41,9 @@
 				scene.add( directionalLight );
 
 				var loader = new Rhino3dmLoader( );
+				loader.setLibraryPath('jsm/libs/rhino3dm/');
 				
-				loader.load( 'models/3ds/portalgun/portalgun.3ds', function ( object ) {
+				loader.load( 'models/3dm/hello_mesh.3dm', function ( object ) {
 
                     /*
 					object.traverse( function ( child ) {
@@ -66,7 +67,7 @@
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				container.appendChild( renderer.domElement );
 
-				controls = new TrackballControls( camera, renderer.domElement );
+				controls = new OrbitControls( camera, renderer.domElement );
 
 				window.addEventListener( 'resize', resize, false );
 

+ 1 - 1
examples/webgl_loader_draco.html

@@ -26,7 +26,7 @@
 		// Configure and create Draco decoder.
 		var dracoLoader = new DRACOLoader();
 		dracoLoader.setDecoderPath( 'js/libs/draco/' );
-		dracoLoader.setDecoderConfig( { type: 'js' } );
+		//dracoLoader.setDecoderConfig( { type: 'js' } );
 
 		init();
 		animate();