webgl_loader_obj2_options.html 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <title>three.js webgl - OBJLoader2 usage options</title>
  5. <meta charset="utf-8">
  6. <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
  7. <link type="text/css" rel="stylesheet" href="main.css">
  8. <style>
  9. #glFullscreen {
  10. width: 100%;
  11. height: 100vh;
  12. min-width: 640px;
  13. min-height: 360px;
  14. position: relative;
  15. overflow: hidden;
  16. z-index: 0;
  17. }
  18. #example {
  19. width: 100%;
  20. height: 100%;
  21. top: 0;
  22. left: 0;
  23. background-color: #000000;
  24. }
  25. #feedback {
  26. color: darkorange;
  27. }
  28. #dat {
  29. user-select: none;
  30. position: absolute;
  31. left: 0;
  32. top: 0;
  33. z-Index: 200;
  34. }
  35. </style>
  36. </head>
  37. <body>
  38. <div id="glFullscreen">
  39. <canvas id="example"></canvas>
  40. </div>
  41. <div id="dat">
  42. </div>
  43. <div id="info">
  44. <a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - OBJLoader2 usage options
  45. <div id="feedback"></div>
  46. </div>
  47. <script src="../build/three.js"></script>
  48. <script src="js/controls/TrackballControls.js"></script>
  49. <script src="js/loaders/MTLLoader.js"></script>
  50. <script src="js/libs/dat.gui.min.js"></script>
  51. <script src="js/loaders/LoaderSupport.js"></script>
  52. <script src="js/loaders/OBJLoader2.js"></script>
  53. <script>
  54. 'use strict';
  55. var WWOBJLoader2Example = function ( elementToBindTo ) {
  56. this.renderer = null;
  57. this.canvas = elementToBindTo;
  58. this.aspectRatio = 1;
  59. this.recalcAspectRatio();
  60. this.scene = null;
  61. this.cameraDefaults = {
  62. posCamera: new THREE.Vector3( 0.0, 175.0, 500.0 ),
  63. posCameraTarget: new THREE.Vector3( 0, 0, 0 ),
  64. near: 0.1,
  65. far: 10000,
  66. fov: 45
  67. };
  68. this.camera = null;
  69. this.cameraTarget = this.cameraDefaults.posCameraTarget;
  70. this.controls = null;
  71. this.flatShading = false;
  72. this.doubleSide = false;
  73. this.cube = null;
  74. this.pivot = null;
  75. };
  76. WWOBJLoader2Example.prototype = {
  77. constructor: WWOBJLoader2Example,
  78. initGL: function () {
  79. this.renderer = new THREE.WebGLRenderer( {
  80. canvas: this.canvas,
  81. antialias: true,
  82. autoClear: true
  83. } );
  84. this.renderer.setClearColor( 0x050505 );
  85. this.scene = new THREE.Scene();
  86. this.camera = new THREE.PerspectiveCamera( this.cameraDefaults.fov, this.aspectRatio, this.cameraDefaults.near, this.cameraDefaults.far );
  87. this.resetCamera();
  88. this.controls = new THREE.TrackballControls( this.camera, this.renderer.domElement );
  89. var ambientLight = new THREE.AmbientLight( 0x404040 );
  90. var directionalLight1 = new THREE.DirectionalLight( 0xC0C090 );
  91. var directionalLight2 = new THREE.DirectionalLight( 0xC0C090 );
  92. directionalLight1.position.set( -100, -50, 100 );
  93. directionalLight2.position.set( 100, 50, -100 );
  94. this.scene.add( directionalLight1 );
  95. this.scene.add( directionalLight2 );
  96. this.scene.add( ambientLight );
  97. var helper = new THREE.GridHelper( 1200, 60, 0xFF4444, 0x404040 );
  98. this.scene.add( helper );
  99. var geometry = new THREE.BoxBufferGeometry( 10, 10, 10 );
  100. var material = new THREE.MeshNormalMaterial();
  101. this.cube = new THREE.Mesh( geometry, material );
  102. this.cube.position.set( 0, 0, 0 );
  103. this.scene.add( this.cube );
  104. this.pivot = new THREE.Object3D();
  105. this.pivot.name = 'Pivot';
  106. this.scene.add( this.pivot );
  107. },
  108. useParseSync: function () {
  109. var modelName = 'female02';
  110. this._reportProgress( { detail: { text: 'Loading: ' + modelName } } );
  111. var scope = this;
  112. var objLoader = new THREE.OBJLoader2();
  113. var onLoadMtl = function ( materials ) {
  114. objLoader.setModelName( modelName );
  115. objLoader.setMaterials( materials );
  116. var fileLoader = new THREE.FileLoader();
  117. fileLoader.setPath( '' );
  118. fileLoader.setResponseType( 'arraybuffer' );
  119. fileLoader.load( 'models/obj/female02/female02.obj',
  120. function ( content ) {
  121. var local = new THREE.Object3D();
  122. local.name = 'Pivot_female02';
  123. local.position.set( 75, 0, 0 );
  124. scope.pivot.add( local );
  125. local.add( objLoader.parse( content ) );
  126. scope._reportProgress( { detail: { text: 'Loading complete: ' + modelName } } );
  127. }
  128. );
  129. };
  130. var onError = function ( event ) {
  131. console.error( 'Error occurred: ' + event );
  132. };
  133. objLoader.loadMtl( 'models/obj/female02/female02.mtl', null, onLoadMtl, null, onError );
  134. },
  135. useParseAsync: function () {
  136. var modelName = 'female02_vertex' ;
  137. this._reportProgress( { detail: { text: 'Loading: ' + modelName } } );
  138. var callbackOnLoad = function ( event ) {
  139. var local = new THREE.Object3D();
  140. local.name = 'Pivot_female02_vertex';
  141. local.position.set( -75, 0, 0 );
  142. scope.pivot.add( local );
  143. local.add( event.detail.loaderRootNode );
  144. scope._reportProgress( { detail: { text: 'Loading complete: ' + event.detail.modelName } } );
  145. };
  146. var scope = this;
  147. var objLoader = new THREE.OBJLoader2();
  148. objLoader.setModelName( modelName );
  149. var fileLoader = new THREE.FileLoader();
  150. fileLoader.setPath( '' );
  151. fileLoader.setResponseType( 'arraybuffer' );
  152. var filename = 'models/obj/female02/female02_vertex_colors.obj';
  153. fileLoader.load( filename,
  154. function ( content ) {
  155. objLoader.parseAsync( content, callbackOnLoad );
  156. scope._reportProgress( { detail: { text: 'File loading complete: ' + filename } } );
  157. }
  158. );
  159. },
  160. useLoadSync: function () {
  161. var modelName = 'male02';
  162. this._reportProgress( { detail: { text: 'Loading: ' + modelName } } );
  163. var scope = this;
  164. var objLoader = new THREE.OBJLoader2();
  165. var callbackOnLoad = function ( event ) {
  166. var local = new THREE.Object3D();
  167. local.name = 'Pivot_male02';
  168. local.position.set( 0, 0, -75 );
  169. scope.pivot.add( local );
  170. local.add( event.detail.loaderRootNode );
  171. scope._reportProgress( { detail: { text: 'Loading complete: ' + event.detail.modelName } } );
  172. };
  173. var onLoadMtl = function ( materials ) {
  174. objLoader.setModelName( modelName );
  175. objLoader.setMaterials( materials );
  176. objLoader.setUseIndices( true );
  177. objLoader.load( 'models/obj/male02/male02.obj', callbackOnLoad, null, null, null, false );
  178. };
  179. objLoader.loadMtl( 'models/obj/male02/male02.mtl', null, onLoadMtl );
  180. },
  181. useLoadAsync: function () {
  182. var modelName = 'WaltHead';
  183. this._reportProgress( { detail: { text: 'Loading: ' + modelName } } );
  184. var scope = this;
  185. var objLoader = new THREE.OBJLoader2();
  186. var callbackOnLoad = function ( event ) {
  187. objLoader.workerSupport.setTerminateRequested( true );
  188. var local = new THREE.Object3D();
  189. local.name = 'Pivot_WaltHead';
  190. local.position.set( -125, 50, 0 );
  191. var scale = 0.5;
  192. local.scale.set( scale, scale, scale );
  193. scope.pivot.add( local );
  194. local.add( event.detail.loaderRootNode );
  195. scope._reportProgress( { detail: { text: 'Loading complete: ' + event.detail.modelName } } );
  196. };
  197. var onLoadMtl = function ( materials ) {
  198. objLoader.setModelName( modelName );
  199. objLoader.setMaterials( materials );
  200. objLoader.terminateWorkerOnLoad = false;
  201. objLoader.load( 'models/obj/walt/WaltHead.obj', callbackOnLoad, null, null, null, true );
  202. };
  203. objLoader.loadMtl( 'models/obj/walt/WaltHead.mtl', null, onLoadMtl );
  204. },
  205. useRunSync: function () {
  206. var scope = this;
  207. var callbackOnLoad = function ( event ) {
  208. scope._reportProgress( { detail: { text: 'Loading complete: ' + event.detail.modelName } } );
  209. };
  210. var prepData = new THREE.LoaderSupport.PrepData( 'cerberus' );
  211. var local = new THREE.Object3D();
  212. local.position.set( 0, 0, 100 );
  213. local.scale.set( 50.0, 50.0, 50.0 );
  214. this.pivot.add( local );
  215. prepData.streamMeshesTo = local;
  216. prepData.addResource( new THREE.LoaderSupport.ResourceDescriptor( 'models/obj/cerberus/Cerberus.obj', 'OBJ' ) );
  217. var callbacks = prepData.getCallbacks();
  218. callbacks.setCallbackOnProgress( this._reportProgress );
  219. callbacks.setCallbackOnLoad( callbackOnLoad );
  220. var objLoader = new THREE.OBJLoader2();
  221. objLoader.run( prepData );
  222. },
  223. useRunAsyncMeshAlter: function () {
  224. var scope = this;
  225. var callbackOnLoad = function ( event ) {
  226. scope._reportProgress( { detail: { text: 'Loading complete: ' + event.detail.modelName } } );
  227. };
  228. var prepData = new THREE.LoaderSupport.PrepData( 'vive-controller' );
  229. var local = new THREE.Object3D();
  230. local.position.set( 125, 50, 0 );
  231. local.name = 'Pivot_vive-controller';
  232. this.pivot.add( local );
  233. prepData.streamMeshesTo = local;
  234. prepData.addResource( new THREE.LoaderSupport.ResourceDescriptor( 'models/obj/vive-controller/vr_controller_vive_1_5.obj', 'OBJ' ) );
  235. prepData.useAsync = true;
  236. var callbacks = prepData.getCallbacks();
  237. var callbackMeshAlter = function ( event ) {
  238. var override = new THREE.LoaderSupport.LoadedMeshUserOverride( false, true );
  239. var mesh = new THREE.Mesh( event.detail.bufferGeometry, event.detail.material );
  240. var scale = 200.0;
  241. mesh.scale.set( scale, scale, scale );
  242. mesh.name = event.detail.meshName;
  243. var helper = new THREE.VertexNormalsHelper( mesh, 2, 0x00ff00, 1 );
  244. helper.name = 'VertexNormalsHelper';
  245. override.addMesh( mesh );
  246. override.addMesh( helper );
  247. return override;
  248. };
  249. callbacks.setCallbackOnMeshAlter( callbackMeshAlter );
  250. callbacks.setCallbackOnProgress( this._reportProgress );
  251. callbacks.setCallbackOnLoad( callbackOnLoad );
  252. var objLoader = new THREE.OBJLoader2();
  253. objLoader.run( prepData );
  254. },
  255. finalize: function () {
  256. this._reportProgress( { detail: { text: '' } } );
  257. },
  258. _reportProgress: function( event ) {
  259. var output = THREE.LoaderSupport.Validator.verifyInput( event.detail.text, '' );
  260. console.log( 'Progress: ' + output );
  261. document.getElementById( 'feedback' ).innerHTML = output;
  262. },
  263. resizeDisplayGL: function () {
  264. this.controls.handleResize();
  265. this.recalcAspectRatio();
  266. this.renderer.setSize( this.canvas.offsetWidth, this.canvas.offsetHeight, false );
  267. this.updateCamera();
  268. },
  269. recalcAspectRatio: function () {
  270. this.aspectRatio = ( this.canvas.offsetHeight === 0 ) ? 1 : this.canvas.offsetWidth / this.canvas.offsetHeight;
  271. },
  272. resetCamera: function () {
  273. this.camera.position.copy( this.cameraDefaults.posCamera );
  274. this.cameraTarget.copy( this.cameraDefaults.posCameraTarget );
  275. this.updateCamera();
  276. },
  277. updateCamera: function () {
  278. this.camera.aspect = this.aspectRatio;
  279. this.camera.lookAt( this.cameraTarget );
  280. this.camera.updateProjectionMatrix();
  281. },
  282. render: function () {
  283. if ( ! this.renderer.autoClear ) this.renderer.clear();
  284. this.controls.update();
  285. this.cube.rotation.x += 0.05;
  286. this.cube.rotation.y += 0.05;
  287. this.renderer.render( this.scene, this.camera );
  288. },
  289. alterShading: function () {
  290. var scope = this;
  291. scope.flatShading = ! scope.flatShading;
  292. console.log( scope.flatShading ? 'Enabling flat shading' : 'Enabling smooth shading');
  293. scope.traversalFunction = function ( material ) {
  294. material.flatShading = scope.flatShading;
  295. material.needsUpdate = true;
  296. };
  297. var scopeTraverse = function ( object3d ) {
  298. scope.traverseScene( object3d );
  299. };
  300. scope.pivot.traverse( scopeTraverse );
  301. },
  302. alterDouble: function () {
  303. var scope = this;
  304. scope.doubleSide = ! scope.doubleSide;
  305. console.log( scope.doubleSide ? 'Enabling DoubleSide materials' : 'Enabling FrontSide materials' );
  306. scope.traversalFunction = function ( material ) {
  307. material.side = scope.doubleSide ? THREE.DoubleSide : THREE.FrontSide;
  308. };
  309. var scopeTraverse = function ( object3d ) {
  310. scope.traverseScene( object3d );
  311. };
  312. scope.pivot.traverse( scopeTraverse );
  313. },
  314. traverseScene: function ( object3d ) {
  315. if ( object3d.material instanceof THREE.MultiMaterial ) {
  316. var materials = object3d.material.materials;
  317. for ( var name in materials ) {
  318. if ( materials.hasOwnProperty( name ) ) this.traversalFunction( materials[ name ] );
  319. }
  320. } else if ( object3d.material ) {
  321. this.traversalFunction( object3d.material );
  322. }
  323. }
  324. };
  325. var app = new WWOBJLoader2Example( document.getElementById( 'example' ) );
  326. var wwObjLoader2Control = {
  327. flatShading: app.flatShading,
  328. doubleSide: app.doubleSide
  329. };
  330. var menuDiv = document.getElementById( 'dat' );
  331. var gui = new dat.GUI( {
  332. autoPlace: false,
  333. width: 320
  334. } );
  335. menuDiv.appendChild( gui.domElement );
  336. var folderOptions = gui.addFolder( 'WWOBJLoader2 Options' );
  337. var controlFlat = folderOptions.add( wwObjLoader2Control, 'flatShading' ).name( 'Flat Shading' );
  338. controlFlat.onChange( function( value ) {
  339. console.log( 'Setting flatShading to: ' + value );
  340. app.alterShading();
  341. });
  342. var controlDouble = folderOptions.add( wwObjLoader2Control, 'doubleSide' ).name( 'Double Side Materials' );
  343. controlDouble.onChange( function( value ) {
  344. console.log( 'Setting doubleSide to: ' + value );
  345. app.alterDouble();
  346. });
  347. folderOptions.open();
  348. // init three.js example application
  349. var resizeWindow = function () {
  350. app.resizeDisplayGL();
  351. };
  352. var render = function () {
  353. requestAnimationFrame( render );
  354. app.render();
  355. };
  356. window.addEventListener( 'resize', resizeWindow, false );
  357. console.log( 'Starting initialisation phase...' );
  358. app.initGL();
  359. app.resizeDisplayGL();
  360. // kick render loop
  361. render();
  362. // Load a file with OBJLoader.parse synchronously
  363. app.useParseSync();
  364. // Load a file with OBJLoader.parseAsync asynchronously using a worker
  365. app.useParseAsync();
  366. // Load a file with OBJLoader.load synchronously
  367. app.useLoadSync();
  368. // Load a file with OBJLoader.load asynchronously
  369. app.useLoadAsync();
  370. // Load a file with OBJLoader.run synchronously
  371. app.useRunSync();
  372. // Load a file with OBJLoader.run asynchronously and add normals during onMeshAlter
  373. app.useRunAsyncMeshAlter();
  374. app.finalize();
  375. </script>
  376. </body>
  377. </html>