123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483 |
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <title>three.js webgl - OBJLoader2 usage options</title>
- <meta charset="utf-8">
- <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
- <link type="text/css" rel="stylesheet" href="main.css">
- <style>
- #glFullscreen {
- width: 100%;
- height: 100vh;
- min-width: 640px;
- min-height: 360px;
- position: relative;
- overflow: hidden;
- z-index: 0;
- }
- #example {
- width: 100%;
- height: 100%;
- top: 0;
- left: 0;
- background-color: #000000;
- }
- #feedback {
- color: darkorange;
- }
- #dat {
- user-select: none;
- position: absolute;
- left: 0;
- top: 0;
- z-Index: 200;
- }
- </style>
- </head>
- <body>
- <div id="glFullscreen">
- <canvas id="example"></canvas>
- </div>
- <div id="dat">
- </div>
- <div id="info">
- <a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - OBJLoader2 usage options
- <div id="feedback"></div>
- </div>
- <script type="module">
- 'use strict';
- import * as THREE from '../build/three.module.js';
- import { GUI } from './jsm/libs/dat.gui.module.js';
- import { TrackballControls } from "./jsm/controls/TrackballControls.js";
- import { VertexNormalsHelper } from "./jsm/helpers/VertexNormalsHelper.js";
- import { MTLLoader } from "./jsm/loaders/MTLLoader.js";
- import { MtlObjBridge } from "./jsm/loaders/obj2/bridge/MtlObjBridge.js";
- import { OBJLoader2 } from "./jsm/loaders/OBJLoader2.js";
- import { OBJLoader2Parallel } from "./jsm/loaders/OBJLoader2Parallel.js";
- import { LoadedMeshUserOverride } from "./jsm/loaders/obj2/shared/MeshReceiver.js";
- const WWOBJLoader2Example = function ( elementToBindTo ) {
- this.renderer = null;
- this.canvas = elementToBindTo;
- this.aspectRatio = 1;
- this.recalcAspectRatio();
- this.scene = null;
- this.cameraDefaults = {
- posCamera: new THREE.Vector3( 0.0, 175.0, 500.0 ),
- posCameraTarget: new THREE.Vector3( 0, 0, 0 ),
- near: 0.1,
- far: 10000,
- fov: 45
- };
- this.camera = null;
- this.cameraTarget = this.cameraDefaults.posCameraTarget;
- this.controls = null;
- this.flatShading = false;
- this.doubleSide = false;
- this.cube = null;
- this.pivot = null;
- };
- WWOBJLoader2Example.prototype = {
- constructor: WWOBJLoader2Example,
- initGL: function () {
- this.renderer = new THREE.WebGLRenderer( {
- canvas: this.canvas,
- antialias: true,
- autoClear: true
- } );
- this.renderer.setClearColor( 0x050505 );
- this.scene = new THREE.Scene();
- this.camera = new THREE.PerspectiveCamera( this.cameraDefaults.fov, this.aspectRatio, this.cameraDefaults.near, this.cameraDefaults.far );
- this.resetCamera();
- this.controls = new TrackballControls( this.camera, this.renderer.domElement );
- let ambientLight = new THREE.AmbientLight( 0x404040 );
- let directionalLight1 = new THREE.DirectionalLight( 0xC0C090 );
- let directionalLight2 = new THREE.DirectionalLight( 0xC0C090 );
- directionalLight1.position.set( -100, -50, 100 );
- directionalLight2.position.set( 100, 50, -100 );
- this.scene.add( directionalLight1 );
- this.scene.add( directionalLight2 );
- this.scene.add( ambientLight );
- let helper = new THREE.GridHelper( 1200, 60, 0xFF4444, 0x404040 );
- this.scene.add( helper );
- let geometry = new THREE.BoxBufferGeometry( 10, 10, 10 );
- let material = new THREE.MeshNormalMaterial();
- this.cube = new THREE.Mesh( geometry, material );
- this.cube.position.set( 0, 0, 0 );
- this.scene.add( this.cube );
- this.pivot = new THREE.Object3D();
- this.pivot.name = 'Pivot';
- this.scene.add( this.pivot );
- },
- useParseMain: function () {
- let modelName = 'female02';
- this._reportProgress( { detail: { text: 'Loading: ' + modelName } } );
- let objLoader2 = new OBJLoader2()
- .setModelName( modelName );
- let scope = this;
- function onLoadMtl ( mtlParseResult ) {
- objLoader2.addMaterials( MtlObjBridge.addMaterialsFromMtlLoader( mtlParseResult ), true );
- let fileLoader = new THREE.FileLoader();
- fileLoader.setPath( '' );
- fileLoader.setResponseType( 'arraybuffer' );
- fileLoader.load( 'models/obj/female02/female02.obj',
- function ( content, message ) {
- let local = new THREE.Object3D();
- local.name = 'Pivot_female02';
- local.position.set( 75, 0, 0 );
- scope.pivot.add( local );
- local.add( objLoader2.parse( content ) );
- scope._reportProgress( { detail: { text: 'Loading of ' + modelName + 'completed: ' + message } } );
- }
- );
- }
- let mtlLoader = new MTLLoader();
- mtlLoader.load( 'models/obj/female02/female02.mtl', onLoadMtl );
- },
- useParseParallel: function () {
- let modelName = 'female02_vertex' ;
- this._reportProgress( { detail: { text: 'Loading: ' + modelName } } );
- let local = new THREE.Object3D();
- local.name = 'Pivot_female02_vertex';
- local.position.set( -75, 0, 0 );
- this.pivot.add( local );
- let scope = this;
- function callbackOnLoad( object3d, message ) {
- local.add( object3d );
- scope._reportProgress( { detail: { text: 'Loading of ' + modelName + 'completed: ' + message } } );
- }
- let materials = {
- tester: new THREE.MeshStandardMaterial()
- };
- let objLoader2Parallel = new OBJLoader2Parallel()
- .setModelName( modelName )
- .setCallbackOnLoad( callbackOnLoad )
- .addMaterials( materials, true );
- let fileLoader = new THREE.FileLoader();
- fileLoader.setPath( '' );
- fileLoader.setResponseType( 'arraybuffer' );
- fileLoader.load( 'models/obj/female02/female02_vertex_colors.obj',
- function ( content ) {
- objLoader2Parallel.parse( content );
- }
- );
- },
- useLoadMain: function () {
- let modelName = 'male02';
- this._reportProgress( { detail: { text: 'Loading: ' + modelName } } );
- let objLoader2 = new OBJLoader2()
- .setModelName( modelName )
- .setUseIndices( true );
- let scope = this;
- function callbackOnLoad ( object3d, message ) {
- let local = new THREE.Object3D();
- local.name = 'Pivot_male02';
- local.position.set( 0, 0, -75 );
- scope.pivot.add( local );
- local.add( object3d );
- scope._reportProgress( { detail: { text: 'Loading of ' + modelName + 'completed: ' + message } } );
- }
- function onLoadMtl ( mtlParseResult ) {
- objLoader2.addMaterials( MtlObjBridge.addMaterialsFromMtlLoader( mtlParseResult ), true );
- objLoader2.load( 'models/obj/male02/male02.obj', callbackOnLoad, null, null, null );
- }
- let mtlLoader = new MTLLoader();
- mtlLoader.load( 'models/obj/male02/male02.mtl', onLoadMtl );
- },
- useLoadParallel: function () {
- let modelName = 'WaltHead';
- this._reportProgress( { detail: { text: 'Loading: ' + modelName } } );
- let local = new THREE.Object3D();
- local.name = 'Pivot_WaltHead';
- local.position.set( -175, 50, 0 );
- let scale = 0.5;
- local.scale.set( scale, scale, scale );
- this.pivot.add( local );
- let objLoader2Parallel = new OBJLoader2Parallel()
- .setModelName( modelName );
- let scope = this;
- function callbackOnLoad ( object3d, message ) {
- local.add( object3d );
- scope._reportProgress( { detail: { text: 'Loading of ' + modelName + 'completed: ' + message } } );
- }
- function onLoadMtl ( mtlParseResult ) {
- objLoader2Parallel.addMaterials( MtlObjBridge.addMaterialsFromMtlLoader( mtlParseResult ), true );
- objLoader2Parallel.load( 'models/obj/walt/WaltHead.obj', callbackOnLoad );
- }
- let mtlLoader = new MTLLoader();
- mtlLoader.load( 'models/obj/walt/WaltHead.mtl', onLoadMtl );
- },
- useLoadMainFallback: function () {
- let local = new THREE.Object3D();
- local.name = 'Pivot_Cerberus';
- local.position.set( 0, 0, 100 );
- let scale = 50;
- local.scale.set( scale, scale, scale );
- this.pivot.add( local );
- let objLoader2Parallel = new OBJLoader2Parallel()
- .setModelName( local.name )
- .setExecuteParallel( false );
- let scope = this;
- function callbackOnLoad ( object3d, message ) {
- local.add( object3d );
- scope._reportProgress( { detail: { text: 'Loading of ' + objLoader2Parallel.modelName + 'completed: ' + message } } );
- }
- objLoader2Parallel.load( 'models/obj/cerberus/Cerberus.obj', callbackOnLoad );
- },
- useLoadParallelMeshAlter: function () {
- let local = new THREE.Object3D();
- local.position.set( 175, -100, 0 );
- local.name = 'Pivot_ninjaHead';
- this.pivot.add( local );
- let objLoader2Parallel = new OBJLoader2Parallel()
- .setModelName( local.name )
- .setBaseObject3d( local );
- // Configure WorkerExecutionSupport to not disregard worker after execution
- objLoader2Parallel.getWorkerExecutionSupport().setTerminateWorkerOnLoad( false );
- function callbackMeshAlter ( event ) {
- let override = new LoadedMeshUserOverride( false, true );
- let mesh = new THREE.Mesh( event.detail.bufferGeometry, event.detail.material );
- mesh.name = event.detail.meshName;
- let helper = new VertexNormalsHelper( mesh, 2, 0x00ff00, 1 );
- helper.name = 'VertexNormalsHelper';
- override.addMesh( mesh );
- override.addMesh( helper );
- return override;
- }
- objLoader2Parallel.setCallbackOnMeshAlter( callbackMeshAlter );
- let scope = this;
- function callbackOnLoad ( object3d, message ) {
- scope._reportProgress( { detail: { text: 'Loading of ' + objLoader2Parallel.modelName + 'completed: ' + message } } );
- }
- objLoader2Parallel.load( 'models/obj/ninja/ninjaHead_Low.obj', callbackOnLoad );
- },
- finalize: function () {
- this._reportProgress( { detail: { text: '' } } );
- },
- _reportProgress: function( event ) {
- let output = '';
- if ( event.detail !== null && event.detail !== undefined && event.detail.text ) {
- output = event.detail.text;
- }
- console.log( 'Progress: ' + output );
- document.getElementById( 'feedback' ).innerHTML = output;
- },
- resizeDisplayGL: function () {
- this.controls.handleResize();
- this.recalcAspectRatio();
- this.renderer.setSize( this.canvas.offsetWidth, this.canvas.offsetHeight, false );
- this.updateCamera();
- },
- recalcAspectRatio: function () {
- this.aspectRatio = ( this.canvas.offsetHeight === 0 ) ? 1 : this.canvas.offsetWidth / this.canvas.offsetHeight;
- },
- resetCamera: function () {
- this.camera.position.copy( this.cameraDefaults.posCamera );
- this.cameraTarget.copy( this.cameraDefaults.posCameraTarget );
- this.updateCamera();
- },
- updateCamera: function () {
- this.camera.aspect = this.aspectRatio;
- this.camera.lookAt( this.cameraTarget );
- this.camera.updateProjectionMatrix();
- },
- render: function () {
- if ( ! this.renderer.autoClear ) this.renderer.clear();
- this.controls.update();
- this.cube.rotation.x += 0.05;
- this.cube.rotation.y += 0.05;
- this.renderer.render( this.scene, this.camera );
- },
- alterShading: function () {
- let scope = this;
- scope.flatShading = ! scope.flatShading;
- console.log( scope.flatShading ? 'Enabling flat shading' : 'Enabling smooth shading');
- scope.traversalFunction = function ( material ) {
- material.flatShading = scope.flatShading;
- material.needsUpdate = true;
- };
- function scopeTraverse ( object3d ) {
- scope.traverseScene( object3d );
- }
- scope.pivot.traverse( scopeTraverse );
- },
- alterDouble: function () {
- let scope = this;
- scope.doubleSide = ! scope.doubleSide;
- console.log( scope.doubleSide ? 'Enabling THREE.DoubleSide materials' : 'Enabling THREE.FrontSide materials');
- scope.traversalFunction = function ( material ) {
- material.side = scope.doubleSide ? THREE.DoubleSide : THREE.FrontSide;
- };
- function scopeTraverse ( object3d ) {
- scope.traverseScene( object3d );
- }
- scope.pivot.traverse( scopeTraverse );
- },
- traverseScene: function ( object3d ) {
- if ( Array.isArray( object3d.material ) ) {
- let materials = object3d.material.materials;
- for ( let name in materials ) {
- if ( materials.hasOwnProperty( name ) ) this.traversalFunction( materials[ name ] );
- }
- } else if ( object3d.material ) {
- this.traversalFunction( object3d.material );
- }
- }
- };
- let app = new WWOBJLoader2Example( document.getElementById( 'example' ) );
- let wwObjLoader2Control = {
- flatShading: app.flatShading,
- doubleSide: app.doubleSide
- };
- let menuDiv = document.getElementById( 'dat' );
- let gui = new GUI( {
- autoPlace: false,
- width: 320
- } );
- menuDiv.appendChild( gui.domElement );
- let folderOptions = gui.addFolder( 'WWOBJLoader2 Options' );
- let controlFlat = folderOptions.add( wwObjLoader2Control, 'flatShading' ).name( 'Flat Shading' );
- controlFlat.onChange( function( value ) {
- console.log( 'Setting flatShading to: ' + value );
- app.alterShading();
- });
- let controlDouble = folderOptions.add( wwObjLoader2Control, 'doubleSide' ).name( 'Double Side Materials' );
- controlDouble.onChange( function( value ) {
- console.log( 'Setting doubleSide to: ' + value );
- app.alterDouble();
- });
- folderOptions.open();
- // init three.js example application
- function resizeWindow () {
- app.resizeDisplayGL();
- }
- function render () {
- requestAnimationFrame( render );
- app.render();
- }
- window.addEventListener( 'resize', resizeWindow, false );
- console.log( 'Starting initialisation phase...' );
- app.initGL();
- app.resizeDisplayGL();
- // kick render loop
- render();
- // Load a file with OBJLoader2.parse on main
- app.useParseMain();
- // Load a file with OBJLoader2Parallel.parse in parallel in worker
- app.useParseParallel();
- // Load a file with OBJLoader.load on main
- app.useLoadMain();
- // Load a file with OBJLoader2Parallel.load in parallel in worker
- app.useLoadParallel();
- // Load a file with OBJLoader2Parallel.load on main with fallback to OBJLoader2.parse
- app.useLoadMainFallback();
- // Load a file with OBJLoader2Parallel.load in parallel in worker and add normals during onMeshAlter
- app.useLoadParallelMeshAlter();
- app.finalize();
- </script>
- </body>
- </html>
|